JavaRush /Java блог /Random UA /Рівні мов програмування
Marat Sadykov
41 рівень

Рівні мов програмування

Стаття з групи Random UA

Вступ

Які бувають мови програмування? Що за концепції в них закладено? Як вони розвивалися? У цій статті розглянемо види мов програмування, ґрунтуючись на так званих рівнях - від машинних кодів (низький рівень, наближений до комп'ютерного "заліза") до таких мов, як Java або С# (високий рівень). Чим менше перетворень пройде текстовий листинг програми шляхом перетворення на набір нулів і одиниць – тим нижчий рівень.
Рівні мов програмування - 1
Далі ми розглянемо:
  1. Мови низького рівня (машинні коди та асемблер)
  2. Середній рівень (C, Фортран ….)
  3. Високий рівень (C++, Java, Python, Ruby, JavaScript...)
Рівень також характеризує наскільки докладно необхідно деталізувати лістинг майбутньої програми реалізації реалізації. Наскільки цей процес є простим для людини. Не варто вважати рівень мови однозначним показником його можливостей. Мова програмування - це інструмент, який ефективний в одній області та менш корисний в інших. І столяр, і тесляр працюють із деревом. У першого основний інструмент – набір стамесок, у другого – сокира. Однак різьблена шафа витонченіше зробить столяр, а будинок швидше поставить тесляр. Хоча кожен і здатний виконати роботу іншого, але зробить це набагато менш ефективним. Різні дані у комп'ютері представлені у вигляді наборів нулів та одиниць. Керуючі команди для її обробки – ті ж дані, що містять у собі інструкції, які визначають місце розташування необхідної інформації та спосіб модифікації.

Машинні мови (найнижчий рівень)

Нам доведеться здійснити короткий візит із Software області до Hardware. Розглянемо у спрощеному вигляді. Процесор - основний "мозок" комп'ютера. Материнська плата, де він встановлено, містить контролери, службовці взаємодії з іншими пристроями через шини (канали даних зв'язку).
Рівні мов програмування - 2
Деякі працюють з великою швидкістю (червоні стрілки): процесор черпає з пам'яті команди та маніпулює даними, відеокарта – особливо у 3D іграх, споживає величезні обсяги текстур, фігур, координат пікселів та інших об'єктів для побудови зображення на екрані монітора. Іншим (через обмеження швидкості обміну інформацією) такі високі показники не потрібні. Різноманітні внутрішні та зовнішні пристрої підключені на схемі зеленими стрілками.

Внутрішній світ процесора

Усі команди процесора надходять із пам'яті виконання у двійковому вигляді. Формат, кількість, підмножина інструкцій залежить від його архітектури. Більшість з них несумісні одна з одною і слідують різним ідеологіям. А також вигляд команди залежить від режиму (8/16/32… розрядність) і джерела даних (пам'ять, регістр, стек…), з якими працює процесор. Одна і та ж дія може бути представлена ​​різними інструкціями. Процесор має команди додавання двох операндів (ADD X,Y) і додавання одиниці до зазначеного (INC X). Додавання трійки до операнда можна виконати як ADD X,3 або триразово викликавши INC X. І, щодо різних процесорів, не можна передбачити який із цих способів буде оптимальним за швидкістю або обсягом пам'яті. Для зручності двійкову інформацію записують у 16-річному вигляді.
int func() {
    int i = getData("7") ;
    return ++i;
   ...
}
Код, що реалізує ті ж дії у вигляді послідовності інструкцій для процесора: ... 48 83 ec 08 bf bc 05 20 00 31 c0 e8 e8 fe ff ff 48 83 c4 08 83 c0 01 ... Ось так, власне, і виглядає низькорівнева мова програмування для процесора intel. Фрагмент, що викликає метод з аргументом та повертає збільшений на одиницю результат. Це і є машинна мова (код), яка передається безпосередньо відразу, без перетворень, на виконання процесору. Плюси:
  • Ми повністю господарі становища, маємо найширші можливості використання процесора та апаратури комп'ютера.
  • Для нас доступні всі варіанти організації та оптимізації коду.
Мінуси:
  • Необхідно мати великі знання з функціонування процесорів і враховувати велику кількість апаратних факторів при виконанні коду.
  • Створення програм трохи складніших, ніж наведений приклад, призводить до різких збільшення витрат часу з написання коду та його налагодження.
  • Платформозалежність: програма, створена для одного процесора, як правило, не функціонуватиме на інших. Можливо, і для даного процесора, в інших режимах його роботи, потрібно буде редагувати код.
Машинні коди широко використовувалися на зорі появи комп'ютерів, інших способів програмування в епоху піонерів ЕОМ не було. На даний час ними зрідка користуються інженери в галузі мікроелектроніки при розробці або низькорівневому тестуванні процесорів.

Мова асемблера (низький рівень)

На відміну від комп'ютера, ми з вами краще сприймаємо інформацію в текстовому/смисловому, а не цифровому вигляді. Ви з легкістю назвете півсотні імен контактів у вашому смартфоні, але навряд чи зможете напам'ять написати відповідні номери телефонів. Аналогічно та з програмуванням. На сходах типів ми піднімемося вище, зробивши три основні кроки:
  • Порівняємо групам цифрових інструкцій процесора, які виконують відповідні дії, одну символьну команду.
  • Виділимо аргументи інструкцій процесора окремо.
  • Введемо можливість назвати області пам'яті, змінні, розташування окремих команд.
Порівняємо фрагменти минулої програми в машинних кодах (по центру) та мовою асемблера (праворуч):
2004b0     48 83 ec 08      sub    $0x8,%rsp
2004b4     bf bc 05 20 00   mov    $0x2005bc,%edi
2004b9     31 c0            xor    %eax,%eax
2004bb     e8 e8 fe ff ff   callq  getData
2004c0     48 83 c4 08      add    $0x8,%rsp
2004c4     83 c0 01         add    $0x1,%eax
Як бачимо, процес написання програми спростився: немає необхідності користуватися довідниками формування цифрових значень команд, розраховувати довжини переходів, розподіл даних у пам'яті її клітинками та інші особливості процесора. Ми описуємо потрібну дію з набору символьних команд і необхідні логіки з виконання аргументів, а далі програма-транслятор переводить текстовий файл на зрозумілий процесору набір нулів і одиниць. Плюси:
  • Процес написання та модифікації коду спростився.
  • Зберігся контроль всіх ресурсів апаратури.
  • Відносно легше переносити програму на інші платформи, але потрібна їхня модифікація залежно від апаратної сумісності.
Мінуси:
  • Асемблер відноситься до низькорівневих мов програмування. Створення навіть невеликих ділянок коду утруднене. До того ж необхідно враховувати специфіку роботи апаратури.
  • Платформозалежність.
Найпопулярніший демонстраційний Java приклад:
public static void main(String[] args) {
    System.out.println("Hello World!");
}
буде виглядати (NASM синтаксис, з використанням Windows API та kernel32.lib) наступним чином:
global _main
	extern  _GetStdHandle@4
	extern  _WriteFile@20
	extern  _ExitProcess@4

	section .text
_main:
	; DWORD  bytes;
	mov 	ebp, esp
	sub 	esp, 4

	; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
	push	-11
	call	_GetStdHandle@4
	mov 	ebx, eax

	; WriteFile( hstdOut, message, length(message), &bytes, 0);
    push	0
	lea 	eax, [ebp-4]
	push	eax
	push	(message_end - message)
	push	message
	push	ebx
	call	_WriteFile@20

	; ExitProcess(0)
	push	0
	call	_ExitProcess@4

	; never here
	hlt
message:
	db  	'Hello, World', 10
message_end:
Як і машинні коди, асемблер частіше використовується інженерами та системними програмістами. На ньому пишуть апаратно-залежні частини ядра операційних систем, критичні за часом або особливості реалізації драйвера різних периферійних пристроїв. Але останнім часом до нього вдаються все рідше, оскільки його застосування сильно звужує переносимість програм на інші платформи. Іноді використовують процес дизассемблирования – створюють асемблерний листинг програми з цифрових кодів для аналізу логіки виконання невеликих фрагментів. В окремих випадках, якщо початковий високорівневий код недоступний: аналіз вірусів для боротьби з ними або втрати вихідного тексту. Мова асемблера зараховують до першого/другого покоління(ми не розглядатимемо окремо псевдокоди до виникнення асемблера та їх відмінність від символьних команд). Хотілося б виділити використання асемблера у Demo Scene (демо-сцена): сплав мистецтва, математики та низькорівневого кодування, що втілюють художні задуми своїх творців у вигляді програм, що генерують відеокліпи при обмеженнях у ресурсах. Часто загальний розмір файлу програми та даних не повинен перевищувати 256 байт (також популярний і формат 4/64 кілобайта). Ось приклад 4 Кб програми:

Мови групи C/Фортран (середній/високий рівень)

З розвитком можливостей обчислювальної техніки обсяг функціональності та термін реалізації коду на асемблері вже не влаштовували. Витрати для написання, тестування та супроводу програм зростали на порядок швидше за їхні можливості. Необхідно було знизити вимоги від програміста щодо знань функціонування апаратури, дати йому інструмент, що дозволяє писати мовами, наближених до людської логіки. Перейти до нових типів мов програмування. Надати можливість розбивати на різноманітні модулі з подальшим послідовним викликом (парадигма процедурного програмування), надати різні типи даних з можливістю їхнього конструювання тощо. Додатково ці заходи привнесли покращену переносимість коду на інші платформи, більш комфортну організацію командної роботи. Однією з перших мов,Фортран . Можливість створювати в текстовому вигляді з описом логіки виконання використовуючи цикли, розгалуження, підпрограми та оперуючи масивами і представляючи дані у вигляді речових, цілих та комплексних чисел приводила інженерів та вчених у захват. За короткий час було створено наукові «фреймворки» та бібліотеки. Все це і стало наслідком того, що Фортран і досі має актуальність, нехай і у вузькому науковому середовищі, і розвивається, оскільки багаж напрацювань дуже великий, тільки бібліотека IMSL активно розвивається з 1970 (!) року, чи багато згадаєте подібних актуальних software -Старожилів? Інша гілка розвитку мов цього рівня – C. Якщо Фортран став інструментом вчених, то C створювався на допомогу програмістам, які створюють прикладне програмне забезпечення: операційні системи, драйвера і т. д. Мова дозволяє вручну управляти розподілом пам'яті, дає прямий доступ до апаратних ресурсів. C-програмістам доводиться контролювати низькорівневі сутності, тому багато хто дотримується думки, що мова C – удосконалений асемблер і його часто називають мовою «середнього» рівня. Привнісши в асемблер типизацію даних, елементи процедурного та модульного програмування мова C і сьогодні є одним з основних для системного програмування, чому також сприяє бурхливий розвиток мікроелектроніки останнім часом. Різні гаджети, контролери, мережеві та інші пристрої потребують драйверів, реалізації протоколів для спільної роботи та інше щодо низькорівневого ПЗ для реалізації взаємодії з апаратурою. Все перераховане вище сприяє затребуваності мови і в даний час. Об'єктно-орієнтовані і функціональні принципи отримали розвиток у вигляді C++, C#, Java, взявши багато від синтаксису C. Плюси:
  • Спрощення процесу створення коду: запровадження типів, розбивка на модулі, скорочення лістингу програм.
  • Прозора логіка закладеного алгоритму внаслідок уникнення машинних кодів до більш зрозумілим для людини командам у семантично описовому стилі.
  • Переносність. Стало достатньо перекомпілювати текст програми для виконання на іншій платформі (можливо з невеликою модифікацією).
  • Швидкість відкомпільованих програм.
Мінуси:
  • Відсутність автоматичного управління пам'яттю та необхідність постійного її контролю.
  • Відсутність реалізації концепцій об'єктно-орієнтованого та функціонального програмування.

Розвиток мов високого рівня

Високорівневі мови програмування, у плані створення ПЗ, стали все більшою мірою віддалятися від машинних кодів і реалізовувати різні, крім процедурного, парадигм програмування. До них відносять також і об'єктно-орієнтованих принципів. C++, Java, Python, JavaScript, Ruby… – спектр мов даного типу найбільш популярний та затребуваний сьогодні. Вони надають більше можливостей для реалізації різноманітного ПЗ і не можна однозначно визначити спеціалізацію кожного з них. Але популярність застосування у відповідних областях обумовлена ​​бібліотеками/фреймворками для роботи з ними, наприклад: JavaScript- Frontend. Мова була розроблена для взаємодії клієнтського веб-браузера з користувачем та віддаленим сервером. Найбільш популярні бібліотеки: Angular, React та VUE. В даний час відносно активно використовується і на web і т. п. серверах (backend), особливо популярний Node.js. Ruby – Backend. Застосовується для створення скриптів (службових сервісних файлів) та на web серверах. Основний фреймворк – Ruby On Rails. Python- Наукова та інженерна сфера (крім веб-області). Є альтернативою стандартним обчислювальним та математичним пакетам (Mathematica, Octave, MatLab…), але має звичну семантику мови та велику кількість бібліотек. Має багато шанувальників у галузі систем машинного навчання, статистики та штучного інтелекту. З бібліотек, що часто використовуються, необхідно згадати django, numpy, pandas, tensorflow. С++– Універсал, еволюційний розвиток мови C. Надає можливості функціонального та об'єктно-орієнтованого програмування та не втративши при цьому здатність низькорівневої взаємодії з апаратним забезпеченням. За рахунок чого реалізується продуктивність і гнучкість під час створення ПЗ, а й ціна відповідає: високий поріг входження рахунок складної специфікації мови, необхідності самостійного контролю над ресурсами і під час програми. Багато однокористувальне та системне ПЗ написано з його застосуванням: модулі операційних систем (Windows, Symbian…), ігри, редактори (Adobe Photoshop, Autodesk Maya…), бази даних (MSSQL, Oracle…), програвачі (WinAmp…) тощо. Слід зазначити, що сучасне ПЗ є складним продуктом,

Подальший прогрес

Останнім часом набирає популярності та інший вид програмування - функціональне (подальший розвиток рівня мови) . Тут вже інший вид абстракції для обчислень – функції, які беруть як аргументи набір функцій та повертають іншу. Роль змінних грають самі функції (звичні нам змінні – просто константні висловлювання, аналогічні final перед оголошенням типу Java). Власне функція замкнута у своїй області видимості, результат роботи залежить тільки від переданих аргументів. Звідси випливають дві чудові властивості:
  • Для тестування нам потрібні лише аргументи функцій (результат роботи не залежить від зовнішніх змінних тощо).
  • Програма у функціональному стилі чудово готова до паралельної роботи: послідовні виклики функцій можна пускати в сусідніх потоках (оскільки на них не діють зовнішні фактори) і їм не потрібні блокування (тобто, проблеми синхронізації відсутні). Хороший стимул приділити час цій темі з огляду на повальне поширення багатоядерних процесорів.
Проте й поріг входження вище, ніж ООП: для ефективного коду необхідно будувати програму, описуючи як функцій алгоритм виконання. Але також для чистого функціонального стилю непогано знати ази логіки і теорії категорій. Найбільш популярні – Haskell, Scala, F#. Але не бійтеся, в Java (як і в інших сучасних мовах третього покоління) з'явабося елементи функціонального програмування та їх можна комбінувати разом з ОВП. Більш детально ви познайомитеся з усіма цими подробицями на онлайн-стажуванні JavaRush. Область логічного програмування (наступний рівень мов)доки знайшла широкого практичного застосування з малої затребуваності. Побудова програм вимагає знання основ дискретної математики, логіки предикатів, засобів обмежень та інших розділів математичної логіки. Найпопулярніша активна мова – Prolog.

Висновок

Нині найпоширеніші – мови ООП. Java, з моменту виникнення, завжди знаходиться в топі, зазвичай у трійці, затребуваних мов. Окрім ООП, містить елементи функціонального програмування, і ви можете комбінувати різні стилі складання ваших програм. Спектр застосування Java дуже широкий – це бізнес завдання, реалізація веб-серверів (backend), основна мова створення Android-додатків, кросплатформові середовища програмування та робочих місць (IDE/АРМ) та моделювання та багато іншого. Особливо сильні позиції Java в Enterprise секторі - області корпоративного програмного забезпечення, яка вимагає якісний і довготривалий код, реалізацію найскладніших бізнес-логік.
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ