Java, C++, Rust. Українські розробники — про еволюцію улюблених мов програмування
За підрахунками Енциклопедії мов програмування, світова історія знає близько 9000 мов, що ґрунтуються на компʼютерному коді. Деякі «динозаври» на кшталт FORTRAN використовуються і донині та отримали безліч ітерацій стандартів. Але лише деякі з них стали безперечними фаворитами сучасних кодерів.
Ми розпитали трьох українських айтівців про мови програмування, з якими вони працюють упродовж свого професійного шляху — Java, C++ та Rust.
Java. Попри думки про звалище історії, мова живе вже 28 років
Сергій Моренець, Java Evangelist, тренер на курсах IT-Discovery, автор книг про Java
Я працюю з Java вже 18 років, починаючи з версії 1.4. Ознайомився з нею цілком випадково. У ті часи програмісти здебільшого використовували 1С та Delphi й працювали в банках чи на невеликі компанії.
А мені пощастило працювати на закордонного замовника, де писали на Visual Basic 6 та C++. Тож згодом, коли проєкт закрився і я залишився без роботи, мене знайшов новий клієнт, який хотів розпочати продукт на Java. Тоді про цю мову мало хто знав, тим паче в Одесі. Я досить швидко її вивчив завдяки бекграунду із С++, на яку вона схожа.
У той час я займався одночасно двома проєктами: один був на Java, інший — на С#. Ці дві мови конкурували, і після двох років роботи в такому режимі стало складно це поєднувати. Потрібно було вибирати щось одне, і я віддав перевагу Java. Насамперед тому, що Java — це open-source проєкт, у якому бібліотеки, фреймворки та інструменти є безплатними, код можна подивитися у відкритих джерелах. Так простіше програмувати та вивчати нові технології. Відтоді я жодного разу не пошкодував про свій вибір.
📜 Історія створення Java
Ідея Java з’явилася ще на початку
Так, у 1995 році Java офіційно зарелізили. Спочатку вона працювала лише для десктопних застосунків (Java SE), мобільних та embedded-пристроїв (Java ME) та аплетів у браузерах. Згодом ера аплетів поступово минула, і 1998 року з’явилася Java 2. Її почали використовувати для корпоративних інформаційних систем, і відтоді вона є мовою розробки, спрямованою на розв’язання проблем бізнесів.
📌 Ключові моменти в розвитку Java
За всю історію ІТ створено тисячі мов програмування. На ринку шалена конкуренція, тож вижити мові без постійного розвитку складно. Однак є нюанс, Java — це три в одному: мова, платформа для запуску Java Virtual Machine (JVM) і набір для розробки Java Development Kit (JDK). У різний час з’являлися конкуренти, які прагнули зайняти нішу Java, наприклад, Kotlin, Scala, Clojure та Groovy. Я регулярно чув розмови про чергових «вбивць Java», однак цього не сталося, адже всі вони запускалися на платформі JVM. Саме тому навіть якби Java вбили як мову, вона залишилася б живою платформою.
Чому я і досі віддаю перевагу Java? Бо вона — не про зміни, а про стабільність і зворотну сумісність. Проєкти, які я написав колись на Java 1.0, компілюватимуться та запускатимуться на Java 19 попри те, що між цими версіями майже 28 років. Я пам’ятаю лише 10 випадків, коли з мови щось видаляли, і це завжди були застарілі ще 20 років тому API. У цьому головна перевага Java: ви можете не побоюватися, що все зламається, якщо використовуватимете новішу версію. Можуть виникнути незначні проблеми, але ніколи — серйозні.
При цьому Java розвивається. Щоправда, до дев’ятої версії оновлення випускали раз на
Однією з найважливіших інфраструктурних фіч, які свого часу з’явилися у Java, став garbage collector — компонент, який дає змогу збирати об’єкти, які не використовуються. Спочатку це були Serial, Parallel, CMS, однак у Java 9 основним став Garbage First (G1). У новіших версіях з’явилися Shenandoah і ZGC, більш інтелектуальні та ефективні, які допомагають отримати кращу продуктивність від Java.
Щодо нових фіч Java для поліпшення розробки, то їх я не можу назвати багато. Це, наприклад, записи (Java records), які дають змогу створювати незмінні об’єкти. Так код працюватиме швидше. Також додався метод зіставлення зі зразком (pattern matching), який дає змогу писати компактніший код.
Уже за часів Java 19 до JDK додали проєкт Loom. Він реалізуватиме так звані віртуальні потоки, чого дуже давно вимагали розробники. Це може стати справжньою революцією, адже Loom дасть змогу писати багатопотокові застосунки простіше: буде менше багів і розробникам треба буде докладати менше зусиль. Раніше для цього використовували спеціалізовані технології реактивного програмування (RxJava, Reactor, Vert.x).
🔮 Чого ще очікують розробники
Колись я сподівався, що в Java додадуть JDBC-драйвер — спеціальний компонент JDK, що відповідає за комунікацію з базами даних. Він фактично не змінювався з перших версій Java і наразі є блокуючим. Джавісти чекають на це 15 років, але якщо проєкт Loom стане основним у Java, то можна обійтися й без цього. Тому нині я очікую, що серйозно поліпшать GraalVM, який дає змогу компілювати Java-застосунки в нативний код. Це працює вже сьогодні, але потребує багато часу. Великі серйозні проєкти компілюються хвилини та десятки хвилин.
Друга річ — це value types, або проєкт Valhalla, тобто об’єкти, які чимось схожі на примітивні типи чи структури. Фактично у Java є два типи змінних: примітиви й об’єкти. Value types — це щось середнє між ними. Вони дають змогу писати компактніші структури даних, які займатимуть менше пам’яті. Проєкт уже є, однак чекаємо, коли він з’явиться в основній гілці Java.
Наостанок скажу, що ще з
Rust. Мова, що стоїть на плечах гігантів
Владислав Фролов, Rust та NEAR ентузіаст, Senior Software Engineer, Pagoda Inc
Я зацікавився ІТ ще в школі, починав з Pascal і Delphi. Уже коли вступив до університету, став опановувати Python. І працював з Python п’ять-сім років, однак мене завжди турбувала швидкодія та досить обмежений продакшн сервісів у цій мові. Кодову базу доводилося постійно підтримувати, що було дедалі складніше під час її зростання. Мова з динамічною типізацією дає змогу швидко працювати, однак згодом хтось має тримати в голові всі можливі проблеми й логіку рішень. Я постійно з цим стикався і почав дратуватися: використовуєте документацію та типізації у Python, додаєте коментарі, описуєте. Однак розуміє код завжди лише той, хто його писав, на продакшені все могло ламатися. Тому, попри всю мою любов до Python, я вирішив шукати далі.
У
Швидкодія забезпечується низькорівневим компілятором LLVM, розробленим на С++. Це оптимізувальний компілятор, який отримує проміжний код, написаний власною мовою програмування. Насправді нею ніхто не пише, це абстракція. На вихід він видає оптимізований код під кожну з платформ, на яких потім запускається
Щодо виразності, то Rust стоїть на плечах гігантів. Коли її починали створювати, існувало багато мов програмування, на які можна було спиратися і звідки перейняти найкращі практики. У Rust можна побачити риси OCaml, C++, Python, C# й низки функціональних мов.
Безпека досягається завдяки синтаксису. З Rust важко припуститися помилки й не помітити її, адже все буде тобі про неї «кричати».
У травні 2015 року відбувся реліз Rust версії 1.0 — це сигнал до спільноти, що все стабільно, можна рухатися далі й розробники не зможуть суттєво зламати мову. Наразі Rust має версію 1.67, і ця одиничка доводить, що мову досі не зламали попри майже вісім років її існування. Коли мова лише з’явилася, вона трохи програвала Python, де можна було робити будь-яку інтеграцію, модулі для графіки чи розрахунків без додаткового прописування програмного коду.
У 2015 році я намагався залучити Rust до проєктів, став писати маленькі консольні застосунки для себе й набивати руку. У планах було перенести все зроблене з Python — на Rust. Побутує думка, що поріг входження в цю мову досить високий, бо тут доводиться всі деталі продумувати наперед. Але я вважаю, що це не залежить від мови, непросто зайти загалом у програмування застосунків високої надійності.
Подекуди мені й нині доводиться повертатися до Python — для одноразових обчислень в інтерактивному режимі, адже Rust не призначена для таких завдань. Rust варто писати продуктові закінчені проєкти, які потребують стабільної роботи з мінімумом змін. Я ще ніколи не мав такого відчуття завершеності, як під час роботи з цією мовою.
📜Історія створення Rust
Я не можу сказати, як усе було насправді. Але є красива історія, яка, гадаю, відсотків на 90 є правдою. У 2006 році співробітник організації Mozilla Research Грейдон Гоар став працювати над мовою програмування Rust. За три роки до розробки долучилася загалом компанія, щоб написати нею браузер Firefox. Історично Firefox створили на С++, однак йому не вистачало швидкодії та ефективного використання ресурсів багатоядерних процесорів.
Як Mozilla Research не намагалися оптимізувати кілька модулів на С++, виникало багато проблем з безпекою коду. Під час перших релізів і додавання нових функцій вилізали помилки з використанням пам’яті, що призводило до аварійної зупинки браузера. Модуль, який відповідав за рендеринг каскадних сторінок стилів (CSS) у браузері, довелося переписувати тричі. Розробники намагалися його розпаралелити, однак це було неможливо через брак надійних інструментів. Їм були потрібні обмеження та більш жорсткі вимоги до володіння даними у програмі.
А в Rust є проста модель володіння змінними, якої не мали інші мови програмування. Вона полягає в тому, що внести зміни до змінної можна за умови, що посилання на неї не мають інші модулі. Інакше читати значення змінної може будь-яка кількість модулів. Це дозволяє будувати прості й надійні програми.
У функціональних мовах програмування на кшталт Erlang та ML для зміни значення змінної потрібно створити нову, з певною модифікацією. Водночас стара залишається. Такі мови побудовані за принципом, що зміна значення змінної — шлях до помилок. Rust працює інакше й дає можливість вносити зміни. Цього й не вистачало Mozilla Research для реалізації безпечної версії браузера.
📌 Ключові моменти в розвитку Rust і те, чого їй бракує
З появою мови Rust з’явився експериментальний веббраузерний рушій Servo, написаний нею, для створення високо розпаралелюваного середовища. Проєкт і надалі розвивається, і частину модулів Servo вже адаптували у Firefox. Нині 10 % браузера написано Rust. Звісно, цей процес потребує багато часу, але він триває, і Rust підхопив проєкт Chromium, який також має на ній модулі.
У 2022 році в Mainline Linux Kernel додали інструментарій для розробки модулів ядра на Rust. Це свідчить про те, що з’являтиметься все більше модулів цією мовою. Про переписування самого ядра не йдеться, але окремі модулі виникатимуть і заходитимуть у невеликі компанії, що виробляють драйвери для свого обладнання. У таких випадках брати за основу Rust значно вигідніше за умовну С, адже розробка йде швидше завдяки ширшому інструментарію.
Нині Rust набуває популярності й сьомий рік поспіль очолює рейтинг найулюбленіших мов серед розробників за опитуванням Stack Overflow. І розвивається не лише мова, а й її бібліотеки та інструменти для розробників у різних галузях. Так, Rust є популярною для розробки високонавантажених серверних застосунків, інструментів для JavaScript; її використовують для оптимізації швидкодії Python-модулів. Але все ще є напрями, де Rust не проявила себе, наприклад, для розробки десктопних і мобільних застосунків. Тут досі бракує ергономічних інструментів.
Попри всі труднощі розробники продовжують переносити внутрішні модулі на Rust і залишають репрезентацію для фронтенду, використовуючи SWIFT, Kotlin, можливо, C++ чи C#. З розвитком мови додаються такі речі, як Higher-Kinded Types (HKT), які дають змогу писати модулі, щоб працювати з широким діапазоном об’єктів. Думаю, у цей напрям буде вкладено ще багато зусиль.
C++. Розширення, яке переросло у повноцінну мову
Влад, С++ розробник
З C++ вперше я стикнувся у школі. Але суто оглядово, тоді я навіть банальний Hello, world! на «плюсах» не написав. Побачив, що це геть не мій рівень, я не розумів, як працювати з оперативною пам’яттю, тому відклав С++ і повернувся до свого кишенькового Pascal, яким я на той момент володів.
Ближче з «плюсами» я ознайомився в університеті. У нас був курс об’єктноорієнтованого програмування (ООП), який чомусь вирішили читати на C++. Крім того, я пішов на додаткове навчання, після якого обіцяли роботу, де знов-таки викладали «плюси». Це схоже на випадковий вибір мови, але я ним дуже задоволений.
📜 Історія створення С++
Якось данський учений Б’ярн Страуструп працював із прекрасною мовою С і виявив у ній фатальний недолік: вона надто низькорівнева, щоби нею можна було писати достатньо складний код за відносно короткий час. З 1979 року він почав роботу над С++, а у 1985 році її офіційно випустили на ринок. Фактично, «плюси» спочатку виникли як розширення мови С з невеликою кількістю додаткових фіч, однією з яких було ООП. Крім того, вона містила те, чого С досі немає, — перевантаження (overloading) функцій за сигнатурою.
Згодом С++ стала самостійною мовою. І С та «плюси» майже цілковито втратили сумісність. Код, написаний на C, перестав компілюватись на С++, адже до C додали фічі, які були непотрібні «плюсам». Наразі С++ несе багаж зворотної сумісності з C, який інколи заважає роботі й розвитку мови.
📌 Ключові моменти в розвитку С++
Довгий час С++ мало чим відрізнялася від С. Фактично лише наявністю класів. Люди були змушені писати все самостійно або шукати шаблони у third-party — бібліотеках сторонніх розробників, що в доінтернетну епоху було складним завданням. Тож одне з найважливіших нововведень, яке заклало принципову різницю між С та «плюсами» — це поява стандартної бібліотеки шаблонів (STL) 1994 року. Бібліотека виникла разом із темплейтами, які дають можливість написати код один раз і використовувати його для різних типів даних. Це був перший серйозний крок у бік перевикористовуваності коду, тому що на С ви не зможете написати функцію, яка буде однаково добре обробляти масив із різними типами даних.
З появою STL «плюси» також отримали string, текстовий рядок. Раніше був просто масив чарів (char — цілочисельний тип даних, значення якого найчастіше інтерпретується як ASCII-символ у вигляді чисел від 0 до 127), з яким розробникам треба було працювати вручну. А string інкапсулював у собі різні утилітарні речі, зменшивши кількість самописного шаблонного коду: наприклад, довжина зберігається прямо в ньому, а для об’єднання рядків не потрібні окремі дії.
Попри свій вік С++ дає широкі можливості керування тим, що відбувається всередині пам’яті, у процесорі. Проблема в тому, що, коли потрібне нестандартне рішення, доводиться писати це самостійно або шукати в сторонній бібліотеці. Це насправді незручно. STL, який ми отримуємо в комплекті, досить обмежений. Кожна його версія має проходити через комітет зі стандартизації С++, а це довго й дорого. Тому зміни відбуваються дуже повільно.
Наприкінці
Першим серед вказівників був auto pointer. Якщо запитати людей, які працювали з «плюсами» ще до появи цього вказівника, вони скажуть, що це була чудова річ, якою в жодному разі не можна було користуватися [усміхається].
З auto pointer виникало багато проблем: у ньому були баги, а більшість розробників використовувала його неправильно. У пізніших стандартах С++ auto pointer розділили на unique, shared і weak. Unique pointer призначений для одноосібного володіння ресурсом, shared, відповідно, — для розділення відповідальності за його володіння. Ну а weak pointer — це таке маленьке віконечко, через яке можна постукатися до ресурсу без захоплення володіння.
Другим наріжним каменем після STL у розвитку «плюсів» став стандарт С++11. До бібліотеки додали багато корисних речей з Boost. Вона максимально наповнена, тут є, здається, усе, що може захотіти написати розробник. З цієї бібліотеки поступово беруть фічі у стандарт і STL. До того ж у С++11 з’явилася можливість працювати з потоками «з коробки». Так вдасться писати насправді кросплатформовий багатопотоковий код без купи шаблонного коду під кожну ОС.
Згодом вийшли стандарти С++14 та С++17, які стали невеликими розширеннями до С++11. Тоді були, зокрема, додані нові бібліотеки, класи STL та алгоритми.
В останньому великому оновленні, стандарті С++20, додали низку нових можливостей. Серед найдовгоочікуваніших та найгучніших: концепції, модулі, співпрограми та діапазони. Концепції — доповнення до шаблонів, які дозволяють обмежувати їхні параметри без перезавантаження, щоб правильно виводити код. Завдяки новій модульній структурі коду відмовилися від директиви #include. Модулі значно прискорюють написання коду та зменшують залежність змінних. Співпрограми — механізм, який допомагає робити асинхронні виклики. Діапазони дають змогу виконувати простіші виклики стандартних алгоритмів і розширюють можливості зв’язування контейнерів і представлень.
💡 Про те, чого не вистачає С++
С++ досі бракує пристойного package-менеджера. Якщо ви працюєте з Windows або принаймні маєте доступ до .NET Stack, можна хитро прикрутити NuGet package manager. Також свій package-менеджер є у фреймворку Qt, він досить поширений, тому дехто помилково вважає, що «плюси» мають власний. Власний package-менеджер дуже спростив би життя. Він потребуватиме менше ручного втручання, достатньо буде відкрити менеджер, «понатискати на кнопочки» — і готово. Нині під’єднання до сторонніх бібліотек виглядає так: ви заходите в інтернет, завантажуєте бібліотеки, хедери, читаєте документацію, потім, з’ясувавши, що вона зібрана не під той компілятор, яким ви користуєтеся, йдете шукати бібліотеку, зібрану правильним компілятором. А потім плачете під час лінкування.
Але попри мінуси та складність С++ житиме. По-перше, на «плюсах» написано багато коду, який досі використовують. По-друге, є люди, які знають цю мову, вони її далі розвиватимуть. По-третє, перевагою С++ є високий ступінь контролю над ресурсами й велика швидкість виконання коду.
С++ — компільована мова, а отже не має зайвих попередніх оптимізацій. Вміло написаний нею код виконується значно швидше, ніж аналогічний код, написаний інтерпретованими мовами. Якщо ви чули, про Python навіть є жарт, що він, як Duracel: працює до десяти разів довше.
Якщо ви є популяризатором якоїсь мови програмування — розкажіть, якої і чому, в коментарях.
11 коментарів
Підписатись на коментаріВідписатись від коментарів Коментарі можуть залишати тільки користувачі з підтвердженими акаунтами.