Объясняем, как компьютер читает написанный код, что происходит внутри вычислительного устройства и почему кодить нужно в определенном порядке.
На фоне новостей о массовых увольнениях в технологических компаниях мало кто обратил внимание еще на один интересный тренд: нехватку высококвалифицированных работников. Парадоксально, но компании, уволившие суммарно 150 тысяч сотрудников, говорят о нехватке талантов. В опросе Deloitte 90% руководителей заявили, что набор и удержание сотрудников остается умеренной или серьезной проблемой.
Кто же нужен? Инженеры, специалисты по обработке данных и разработчики с опытом работы в области искусственного интеллекта пользуются большим спросом. Сложно найти и специалистов по кибербезопасности. Спрос, превышающий предложения, говорит о том, что фундаментальные знания и качественная подготовка могут сыграть большую роль в карьере программиста и, возможно, защитят его во время волны массовых увольнений.
Зачем это нужно знать
Глубокие знания в этой области облегчают диагностику сложных ошибок, повышают безопасность ПО и упрощают понимание, как взаимодействуют программное и аппаратное обеспечение.
Также вам будет проще изучать языки программирования, алгоритмы и структуру данных. Эти знания подготовят к эффективной разработке программ, пониманию архитектуры процессора и операционных систем, а также к созданию надежных и безопасных приложений.
Рассказываем, как компьютер читает написанный код, что происходит внутри устройства и почему кодить нужно в определенном порядке.
Сразу под капот
Компьютерный код — это набор инструкций для процессора, которые он выполняет и выдает конечный результат. Инструкции поступают на процессор в виде электронных сигналов, и на выходе мы тоже получаем электронный сигнал — только другой, в виде результата.
Сигналы поступают по проводам — шинам. Их обрабатывают транзисторы – электронные элементы, которые могут быть только в двух состояниях: включено 1 и выключено 0.
Как вы видите на рисунке, из транзистора торчит три проводка – один на вход, один на выход и один для контроля – включения или выключения потока электричества.
Конечно, сейчас транзисторы в процессорах выглядят совсем не так. Они уменьшились до микроскопических размеров. Итак, у нас всего лишь нули и единицы, но давайте учтем, что в современных процессорах транзисторов десятки миллиардов и каждый из которых может включаться и выключаться тысячи раз в секунду. Из них выстраивают логические схемы: в следующих статьях мы еще подробнее рассмотрим как все работает на уровне “железа”. А сейчас просто скажем, что компьютеру нужен код в виде нулей и единиц.
Первые программисты, если можно применить это слово, работали с кучей проводов и переключателей. Программирование представляло собой сложный механический процесс, при котором надо было направить электронный сигнал c десятков переключателей на устройство, состоящее из вакуумных трубок, диодов и резисторов. Это занимало дни и недели. Ответ тоже выдавался электрическими сигналами и распечатывался в виде перфокарт, в которых нули и единицы были представлены как наличие отверстия (0) или отсутствие отверстия (1).
Спойлер
При всем при этом первые громоздкие компьютеры, занимавшие целые этажи, работали быстрее и безошибочнее сотен людей с математическим образованием. Это было значительным прогрессом, так одна из программ первого компьютера ENIAC представляла собой моделирование распада нейтрона во время деления ядра. Это дало полезные и ранее неизвестные ответы. Впервые компьютер был использован в качестве реального симулятора задач, которые невозможно решить с помощью традиционной математики.
Специалисты всегда искали способы работать более эффективно, поэтому компьютеры уменьшались, внедрялись новые технологии. Однако те же самые принципы — “Архитектура фон Неймана” — используются и сейчас. Их автором является математик Джон фон Нейман, разработавший такую архитектуру еще в 1946 году.
Самым главным следствием этих принципов можно назвать то, что теперь программа уже не была постоянной частью машины (как например, у калькулятора). Программу стало возможно легко изменить. А вот аппаратура, конечно же, остается неизменной, и очень простой.
Как пишут код
Мы уже разбирали, как языки программирования пришли к современному виду и почему программисты уже не пишут программы из нулей и единиц – это слишком трудозатратно. Большинство программистов используют языки программирования высокого уровня. Программы представляют собой текстовые файлы, которые, в принципе, может прочитать и неподготовленный человек.
Это программа для простой сортировки слов по алфавиту. Этот код сначала определяет массив строк с названиями фруктов. Затем он использует метод Arrays.sort() для сортировки элементов массива по алфавиту. Потом код перебирает отсортированный массив с помощью цикла for-each и выводит каждый элемент на экран.
Обратите внимание, согласно принципам фон Неймана, каждую строчку кода для компьютера пишут по порядку и выполняет он ее тоже по порядку.
Однако очень часто разработчикам нужно создать программы, при выполнении которых компьютер будет читать разные участки кода. И это тоже разрешено принципами фон Неймана.
В этом примере представлена программа, которая считает сумму двух чисел. Это наглядно продемонстрирует, как осуществляется переход на другой участок кода.
import java.util.Scanner; // Импортируем класс Scanner для считывания ввода пользователя
public class SimpleCalculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in); // Создаем объект Scanner для чтения ввода с консоли
// Запрашиваем у пользователя два числа
System.out.print(«Введите первое число: «);
int firstNumber = scanner.nextInt();
System.out.print(«Введите второе число: «);
int secondNumber = scanner.nextInt();
// Вызываем метод для вычисления суммы и выводим результат
int sum = calculateSum(firstNumber, secondNumber);
System.out.println(«Сумма: » + sum);
}
// Метод для вычисления суммы двух чисел
public static int calculateSum(int num1, int num2) {
return num1 + num2;
}
}
В этой программе:
- Импортируется класс Scanner из пакета java.util для считывания ввода пользователя.
- В методе main создается объект Scanner для чтения данных, введенных пользователем в консоль.
- Программа запрашивает у пользователя ввести два числа, которые сохраняются в переменных firstNumber и secondNumber.
- Далее, программа вызывает метод calculateSum, передавая ему введенные пользователем числа в качестве аргументов. Метод calculateSum вычисляет и возвращает сумму этих чисел.
- Результат работы метода calculateSum (сумма двух чисел) выводится на экран.
При запуске представленной программы пользователь увидит следующий процесс на экране своего компьютера:
- Запрос первого числа: Программа сначала выводит сообщение «Введите первое число: «. Это приглашение для пользователя ввести число с клавиатуры. Курсор будет мигать в ожидании ввода.
- Ввод первого числа: Пользователь вводит число и нажимает Enter. Введенное число сохраняется в переменную firstNumber.
- Запрос второго числа: Сразу после ввода первого числа программа выводит второе сообщение: «Введите второе число: «. Это снова приглашение к действию, и курсор ожидает ввода второго числа.
- Ввод второго числа: Пользователь вводит второе число и нажимает Enter. Это число сохраняется в переменную secondNumber.
- Вывод результата: После того как пользователь ввел оба числа, программа вычисляет их сумму с помощью метода calculateSum и выводит результат на экран в формате «Сумма: X», где X — это сумма введенных чисел.
- Весь процесс является интерактивным и требует от пользователя активного участия путем ввода данных. После вывода результата выполнение программы завершается, если в программе не предусмотрено дальнейших действий.
Чтобы понять, что такое объект, класс и метод, вы можете почитать статью “Зачем изучать ООП и как эти знания облегчат вам жизнь”.
Как эти знания пригодятся в будущем?
Программистам важно понимать основные принципы архитектуры компьютеров, на которых они работают, и учитывать их при разработке ПО. Разработчик, игнорирующий принципы этой архитектуры, может столкнуться с рядом ошибок и проблем в своих программах:
- Неправильное управление памятью: Игнорирование того, что инструкции и данные используют одну и ту же память, может привести к ошибкам, когда программа случайно перезаписывает свой собственный код (инструкции), что может привести к непредсказуемому поведению программы или к её аварийному завершению.
- Проблемы с безопасностью: Несоблюдение изоляции между исполняемым кодом и данными может привести к уязвимостям в программе, например, к уязвимостям типа «выполнение кода» или «переполнение буфера», когда злоумышленник может внедрить и выполнить произвольный код.
- Неправильное кэширование: Неучет того, как архитектура фон Неймана взаимодействует с кэш-памятью, может привести к неэффективному использованию кэша. Например, чрезмерное использование памяти для данных может вытеснить инструкции из кэша, что замедлит выполнение программы из-за частых обращений к основной памяти.
- Неэффективное использование памяти и процессора: Программист, не учитывающий особенности архитектуры фон Неймана, может создать программу, которая неэффективно использует память или процессор, например, из-за частых перемещений данных между памятью и регистрами процессора без необходимости.
- Ошибки в алгоритмах: Игнорирование того, как архитектура влияет на последовательность выполнения инструкций, может привести к неправильному проектированию алгоритмов, когда предполагается параллельное выполнение операций, которое невозможно из-за последовательной природы архитектуры фон Неймана.
Профессию “Java-разработчик” можно освоить на курсе DAR University всего за 6 месяцев. За это время обучающиеся получают практический опыт и работают над проектами, которые можно продемонстрировать будущим работодателям в портфолио.
Автор статьи и заглавного изображения: Алишер Ахметов
Редактор: Роман Лукьянчиков