Oczywiście w naszej buńczucznej tezie wybrzmiewa spora przesada. Ale zastanówmy się - języki działające na maszynach wirtualnych zostały opracowane, aby ułatwić wdrażanie na dowolnej platformie. Czy ta możliwość nie straciła na znaczeniu gdy oprogramowanie działa dziś w kontenerze?
C# jak COBOL
Na szczęście nawet coś przestarzałego niekoniecznie oznacza, że nie jest już używane lub ważne. Taki na przykład COBOL jest przestarzały bo nie jest już potrzebny do rozwiązywania konkretnych problemów. Nie oznacza to jednak, że możemy zamknąć każdy system z uruchomionym językiem COBOL lub przestać pisać kod w tym języku. COBOL nadal ma znaczenie, ponieważ nadal działają na nim choćby duże, starsze systemy obsługujące kluczowe systemy finansowe.
Nie przepisuje się milionów wierszy działającego kodu tylko dlatego, że technologia użyta do jego tworzenia jest w dużej mierze przestarzała. Chodzi raczej o to, że gdybyśmy wyobrazili sobie, że wszystkie te systemy znikną jutro z powodu jakiegoś kosmicznego wypadku i trzeba by było je odtworzyć, czy użylibyście do tego COBOLa? Czy COBOL miałby istotne zalety, przynosząc znaczne korzyści przy tworzeniu tych systemów? Nie, mamy dziś lepsze technologie do budowy od zera.
JVM zastąpione przez wirtualną maszynę Linuksa
Java i C# są w podobnej sytuacji. Czy stworzyłbyś dziś język systemów ukierunkowany na maszynę wirtualną w celu tworzenia systemów korporacyjnych w chmurze? Raczej nie. Przed powstaniem chmury kontenerowej sensowne było wdrażanie oprogramowania na dowolnym serwerze w postaci pliku .jar. W pewnym sensie można by pomyśleć o wirtualnej maszynie języka Java jako o tworzeniu własnego małego kontenera.
Dzięki Dockerowi lub innym technologiom kontenerowym idziemy o krok dalej. Zamiast Wirtualnej Maszyny Javy mamy coś, co można by nazwać „Wirtualną Maszyną Linuksa”. To Linux, a nie API Java, stał się wspólnym mianownikiem. Po prostu piszesz oprogramowanie, które będzie działało w jakimś środowisku Linux, które możesz utworzyć za pomocą kontenera Docker et voilà - możesz uruchamiać je w dowolnym miejscu.
Zamiast uruchamiać przez system operacyjny wirtualną maszynę Java lub środowisko .NET, uruchamiasz kontener Docker, który tworzy odpowiednik maszyny wirtualnej Linux na dowolnym używanym systemie operacyjnym.
W efekcie masz całe środowisko systemu operacyjnego z systemami plików, usługami systemu operacyjnego, które możesz wykorzystać. Możesz używać różnych programów napisanych w dowolnym języku. Podejście Java i C# oznaczało tworzenie środowiska uruchomieniowego, w którym można by tworzyć specjalne warianty językowe tworzące kod dla konkretnej maszyny wirtualnej.
Po co dziś tworzyć wszystkie te alternatywne wersje każdego języka, aby działały na tej samej maszynie wirtualnej, aby umożliwić interakcję, skoro można po prostu uruchomić je wszystkie w tym samym kontenerze Docker?
Różnice w podejściu Java i C#
Zaznaczmy, że mówiąc o języku C# chodzi właściwie o całe środowisko.NET. Kluczowa różnica w porównaniu z Javą polega na tym, że C# zazwyczaj używa tak zwanego natywnego generatora obrazów (NGEN). To wciąż strategia kompilacji just-in-time ale polegająca na tym, że JIT utworzy w pamięci masę kodu natywnego. Ta reprezentacja pamięci całego skompilowanego kodu jest zwykle nazywana obrazem.
Sprawdź oferty pracy na TeamQuest
Wiele języków opartych na JIT pozwala na zrzucenie tego obrazu do pliku, aby uniknąć konieczności ponownego wykonywania tych samych operacji JIT. Jednak to nie to samo, co kompilacja. Nie masz gwarancji, że udało Ci się zJITować wszystko, więc nadal potrzebujesz środowiska uruchomieniowego i kompilatora JIT, gdy później uruchomisz ten kod. Po prostu unikasz wielokrotnego ponownego kompilowania tych samych często używanych funkcji.
To samo dotyczy świata .NET z NGEN. Nie kompiluje wszystkiego do kodu natywnego. Nadal potrzebujesz środowiska uruchomieniowego i kompilatora JIT, aby uruchomić utworzone pliki obrazów. W szczególności są one potrzebne do interakcji z .NET assemblies (odpowiednikami bibliotek DLL). Dlatego też w 2017 roku Microsoft stworzył to, co nazywają sobie natywnym .NET. Ale to już historia na inny wpis…