Maszyny nie znają angielskiego
Kiedy po raz pierwszy uczyłem się języka C w szkole, było coś, czego najbardziej nie rozumiałem. „Dlaczego mój kod nie działa od razu, ale czy musi przejść irytujący proces budowania i kompilacji?”.
Python uruchamia się natychmiast po napisaniu kodu i naciśnięciu klawisza Enter, ale Java i C wymagają czasochłonnych kroków. Kiedy byłem studentem, pomyślałem: „Każdy język ma inną gramatykę”. Kiedy przystępowałem do testu, wystarczyło odpowiedzieć „C to język kompilowany, a Python to język interpretowany”.
Jednak pracując z serwerami zaplecza, które w praktyce obsługują duże ilości ruchu, zdałem sobie sprawę, że ta prosta różnica stanowiła ogromną barierę determinującą wydajność i szybkość wdrażania systemu. Elegancki kod, który napisałem, był w rzeczywistości po prostu nieznanym, obcym językiem dla ignoranta i sumiennego pracownika zwanego CPU.

Co to jest, do cholery, „kompilacja”?
Czym dokładnie jest kompilacja? Czym to się różni od zwykłego „oszczędzania”?
Napisany przez nas kod źródłowy (.java, .c) to tak naprawdę plik tekstowy. Jest to „tekst”, który można odczytać nawet po otwarciu notatnikiem. Jednak komputery (procesory) nie potrafią czytać. Można jedynie wiedzieć, czy prąd płynie (1), czy nie (0).
Kompilacja to kompleksowy proces pakowania, który konwertuje zapisany przez nas „plik tekstowy” na „plik wykonywalny (.exe, .class, .jar), który może uruchomić komputer.
Innymi słowy, jeśli kod źródłowy to „przepis na gotowanie (papier)”, kompilacja to proces przycinania i smażenia składników zgodnie z przepisem oraz serwowania „gotowego dania (jedzenia)”. Bez względu na to, jak bardzo zmodyfikujesz przepis (kod), jeśli nie ugotujesz go (zbudujesz) ponownie, zimne jedzenie, które zrobiłeś wczoraj, pozostanie na stole (serwerze).
Instrukcje pracy dla cyfrowego centrum dystrybucji
Aby zrozumieć ten złożony proces, porównaj wnętrze komputera z gigantycznym cyfrowym centrum logistycznym.
W tym przypadku CPU to procesor, który jest niewiarygodnie szybki, ale ma zerową elastyczność. Ten pracownik może czytać tylko instrukcje pracy zwane językiem maszynowym (0 i 1).
Pisanie kodu w języku Java lub Python to proces tworzenia „podręcznika pracy”, który można przekazać pracownikom. Problem w tym, że tę instrukcję piszemy po angielsku (języku programowania). Pracownik nie zna języka angielskiego. Dlatego potrzebujemy tłumaczy. Od tej metody tłumaczenia zależy los języka.
1. Kompilator: Profesjonalny tłumacz, który tłumaczy z wyprzedzeniem
2. Tłumacz: Tłumacz symultaniczny w czasie rzeczywistym

[Weryfikacja kodu] Weryfikacja samego języka maszynowego
Naprawdę nie mogę tego poczuć, słysząc to. Sprawdźmy wizualnie, czy Python rzeczywiście tłumaczy wiersz po wierszu i jak wygląda kod widziany przez maszynę.
Python ma moduł o nazwie dis (Dezasembler). Dzięki temu możesz zobaczyć, które instrukcje są wewnętrznie podzielone na kod Pythona podczas jego wykonywania.
import dis
def my_function():
a = 10
b = 20
print(a + b)
# Sprawdz, na jaki kod maszynowy (bytecode) jest konwertowany kod Pythona
print("--- Python Bytecode Verification ---")
dis.dis(my_function)
Po uruchomieniu tego kodu wyświetlane są następujące obce języki.
5 0 LOAD_CONST 1 (10)
2 STORE_FAST 0 (a)
6 4 LOAD_CONST 2 (20)
6 STORE_FAST 1 (b)
7 8 LOAD_GLOBAL 0 (print)
10 LOAD_FAST 0 (a)
12 LOAD_FAST 1 (b)
14 BINARY_ADD
16 CALL_FUNCTION 1
18 POP_TOP
20 LOAD_CONST 0 (None)
22 RETURN_VALUE
Analiza:
Z drugiej strony, po skompilowaniu język C jest bezpośrednio tłumaczony na rzeczywisty język asemblera procesora, taki jak MOV EAX, 10 (umieść 10 w rejestrze EAX). Ponieważ nie ma menedżerów średniego szczebla, nie ma innego wyjścia, jak tylko działać szybko.
Kompromis w praktyce: który wybrać?
Kiedy byłam studentką, najważniejsza była wygoda. Zamiast języka C, w którym występują błędy kompilacji, wolałem Pythona lub JavaScript, który można łatwo napisać i uruchomić. Jednak w praktyce należy dokonać ostrego kompromisu między stabilnością a produktywnością.
1. Strach przed błędami wykonania (słabość interpretera)Najbardziej przerażającą rzeczą podczas budowania serwera w Pythonie jest to, że serwer zatrzymuje się o 3 w nocy z powodu pojedynczej literówki. Interpreter nie wie o błędzie, dopóki nie zostanie uruchomiony (punkt, w którym wykonywany jest kod). Z drugiej strony Java (język skompilowany) pyta: „Popełniłem literówkę?” podczas tworzenia kodu. I on mi mówi. Ta rygor w wychwytywaniu błędów przed wdrożeniem staje się wybawieniem w projektach na dużą skalę.
2. Nudny czas kompilacji (słabość kompilatora) Z drugiej strony, gdy projekt Java się rozrasta, modyfikacja i sprawdzenie pojedynczej linii kodu może zająć kilka minut (Gradle Build…). Właśnie dlatego Python jest w przeważającej mierze używany na wczesnych etapach startupów, gdzie krytyczne są szybkie modyfikacje i wdrożenia, lub w zadaniach wymagających natychmiastowych wyników, takich jak analiza danych.

Wniosek: teoria staje się bronią
Teraz wiemy, że proces „kompilacji i kompilacji” oraz sposób tłumaczenia kodu różnią się w zależności od języka. Teoretycznie właściwym rozwiązaniem byłby wybór najlepszego języka w zależności od charakteru projektu.
Ale rzeczywistość nie była taka łaskawa. Firma, do której dołączyłem, miała już ustalony stos technologii i chociaż dołączyłem jako programista Java, musiałem dotknąć Pythona, JavaScript, a nawet XML Androida.
Paradoksalnie, tym, co uratowało mnie z tej zagmatwanej dziedziny „wszystkożernego rozwoju”, były „podstawowe teorie”, których się dzisiaj nauczyłem. Dzieje się tak dlatego, że chociaż powłoka języka jest inna, zasady w nim działające są takie same.
Następnym razem opowiem o moich praktycznych doświadczeniach o tym, jak „zagłębiłem się w jeden język (Java), aby kierować reklamy na inne języki” i dlaczego podstawy są ważne, aby uniknąć stania się niewolnikiem frameworku.