Hack: nowy język programowania dla HHVM – Inżynieria Facebooka

Śpieszysz się? Wypróbuj Hack już teraz: http://hacklang.org/

Dzisiaj udostępniamy Hack, język programowania, który opracowaliśmy dla HHVM i który bezproblemowo współpracuje z PHP. Hack godzi szybki cykl rozwoju PHP z dyscypliną zapewnianą przez statyczne typowanie, jednocześnie dodając wiele funkcji powszechnie spotykanych w innych nowoczesnych językach programowania.

Wdrożyliśmy Hack w Facebooku i okazał się on wielkim sukcesem. W ciągu ostatniego roku, zmigrowaliśmy prawie całą naszą bazę kodów PHP do Hacka, zarówno dzięki organicznemu przyjęciu, jak i wielu domorosłym narzędziom do refaktoryzacji.

Jesteśmy również dumni z tego, że udostępniliśmy publicznie wersję open source Hacka na stronie http://hacklang.org/ jako część naszej platformy uruchomieniowej HHVM, która będzie teraz wspierać zarówno Hacka, jak i PHP.

Motywacja

Każdy programista PHP jest zaznajomiony z codziennymi zadaniami, które mogą być trudne lub uciążliwe. Powyższy kod jest świetnym przykładem częstego błędu, gdzie metoda może zostać nieoczekiwanie wywołana na obiekcie null, powodując błąd, który nie zostanie wyłapany aż do czasu wykonania. Innym przykładem jest złożone API, gdzie programiści mogą mieć solidne zrozumienie jego semantyki, ale nadal spędzają czas na szukaniu prozaicznych nazw metod w dokumentacji.

W skali Facebooka – z tysiącami inżynierów wysyłających nowy kod dwa razy dziennie – spowolnienia takie jak te są jeszcze bardziej problematyczne. Przed Hack’iem mieliśmy prosty język z szybką pętlą sprzężenia zwrotnego – ale jak mogliśmy złagodzić problemy opisane powyżej? Czy wczesne wykrywanie błędów może współistnieć z szybką iteracją, przy jednoczesnym zachowaniu naszej inwestycji w PHP? Czy ulepszona analiza kodu i introspekcja pomogłyby uczynić programistów bardziej produktywnymi dzięki narzędziom takim jak autouzupełnianie?

Tradycyjnie, dynamicznie typowane języki pozwalają na szybki rozwój, ale poświęcają zdolność do wczesnego wychwytywania błędów i szybkiej introspekcji kodu, szczególnie w przypadku większych baz kodu. I odwrotnie, języki statycznie typowane zapewniają większe bezpieczeństwo, ale często kosztem szybkiej iteracji. Wierzyliśmy, że musi istnieć słodki punkt.

W ten sposób narodził się Hack. Wierzymy, że oferuje on to, co najlepsze w dynamicznie i statycznie typowanych językach, i że będzie wartościowy dla projektów każdej wielkości.

Język Hack

Hack ma głębokie korzenie w PHP. W rzeczywistości, większość plików PHP jest już poprawnymi plikami Hacka. Dokonaliśmy świadomego wyboru, aby nie wspierać kilku przestarzałych funkcji i cech, które były niekompatybilne z typowaniem statycznym (np. „zmienne zmienne” i funkcja extract()). Dodaliśmy również wiele nowych funkcji, które naszym zdaniem pomogą uczynić programistów bardziej produktywnymi.

Naszym głównym dodatkiem jest statyczne typowanie. Opracowaliśmy system do oznaczania sygnatur funkcji i członków klasy informacjami o typie; nasz algorytm sprawdzania typu („type checker”) wywnioskował resztę. Sprawdzanie typów jest przyrostowe, więc nawet w pojedynczym pliku część kodu może zostać przekonwertowana do Hacka, podczas gdy reszta pozostaje dynamicznie typowana. Technicznie rzecz biorąc, Hack jest językiem „stopniowo typowanym*”*: dynamicznie typowany kod bezproblemowo współpracuje z kodem typowanym statycznie.

W ramach systemu typów Hacka, wprowadziliśmy kilka cech takich jak generyczność, typy nullable, aliasing typów i ograniczenia na parametry typów. Te nowe cechy języka nie rzucają się w oczy, więc kod napisany z Hackiem nadal będzie wyglądał i czuł się jak dynamiczny język, do którego programiści PHP są przyzwyczajeni.

Jednakże, Hack dodaje dodatkowe funkcje poza statycznym sprawdzaniem typów, włączając w to Kolekcje, wyrażenia lambda, oraz egzekwowanie typów zwracanych i typów parametrów w czasie rzeczywistym.

Kolekcje zapewniają czystą, bezpieczną dla typów alternatywę dla tablic PHP. Zaprojektowaliśmy je specjalnie tak, aby dobrze współpracowały z typowaniem statycznym i generycznymi. API Kolekcji oferuje wiele klasycznych funkcji wyższego rzędu, takich jak map() i filter(), aby ułatwić funkcjonalne style programowania.

Wyrażenia lambda dają zwięzłą składnię do tworzenia domknięć. Podczas gdy PHP posiada domknięcia, wymaga to od programisty jawnego nazwania zmiennych, które muszą być użyte z zamkniętych zakresów. Dzięki wyrażeniom lambda w Hacku, automatycznie wnioskujemy o tych zastosowaniach, oszczędzając Ci niepotrzebnej pracy. Wyrażenia lambda sprawiają, że wygodniej jest w pełni korzystać z API Collections.

Wyegzekwowanie w czasie rzeczywistym typów zwracanych i typów parametrów (w tym typów skalarnych, takich jak int i string) zapewnia bezpieczeństwo wykraczające poza to, co można sprawdzić statycznie, podczas gdy adnotacje typu są stopniowo dodawane do bazy danych. Egzekwowanie w czasie rzeczywistym pomaga programistom łatwiej wykrywać i diagnozować pewne rodzaje problemów, a także pomaga JIT HHVM produkować bardziej wydajny kod, czyniąc go bezpiecznym, aby zaufać adnotacjom typu dla celów optymalizacji.

Instantaneous type checking

Podczas rozwoju, programista PHP zazwyczaj szybko przechodzi tam i z powrotem pomiędzy kodem źródłowym a przeglądarką. Inżynierowie mogą iterować tak szybko, jak tego potrzebują, testując i dostrajając doświadczenie, aż będzie idealne.

Tradycyjnie, sprawdzanie typów zakłóciłoby tę pętlę sprzężenia zwrotnego, ponieważ analiza kodu źródłowego wymaga czasu. Nie chcieliśmy spowalniać przepływu pracy w PHP, więc wymyśliliśmy nowe podejście, aby pogodzić natychmiastową informację zwrotną z bezpieczeństwem typów.

Naszym rozwiązaniem było zaprojektowanie sprawdzania typów jako lokalnego serwera, który obserwuje system plików. Serwer przechowuje wszystkie informacje o kodzie źródłowym w pamięci i automatycznie aktualizuje się, gdy plik zmienia się na dysku. To podejście opłaciło się: sprawdzanie typów zwykle działa w czasie krótszym niż 200 milisekund i rzadko zajmuje więcej niż sekundę, co czyni go łatwym do zintegrowania z tokiem pracy dewelopera bez wprowadzania zauważalnego opóźnienia.

Migracja kodu

Korzyści płynące z Hacka związane z bezpieczeństwem typów i refaktoryzacją rosną im więcej jest on używany w bazie kodu. Rozumiejąc, że dla niektórych kodów trudno byłoby od razu całkowicie przejść na Hacka, ważne było dla nas, aby Hack był rozwijany w taki sposób, aby mógł współistnieć bezpośrednio z innymi plikami PHP, gdy jest wprowadzany stopniowo.

Reszta procesu konwersji, taka jak dodawanie adnotacji typów i używanie nowych funkcji języka, może być wykonana w sposób odpowiedni dla danej bazy kodowej. Na przykład, adnotacja typu może być dodana dla jednej funkcji, ale pominięta w innej funkcji, nawet w tym samym pliku. Jeśli parametr funkcji lub członek klasy nie ma jawnej adnotacji typu, sprawdzacz typów uznaje jego typ za dynamiczny i nie sprawdza typu tej wartości.

W obrębie Facebooka stwierdziliśmy, że nasi inżynierowie docenili Hacka na tyle, że zaczęli dobrowolnie konwertować większość własnego kodu. Mając miliony linii kodu w naszym drzewie, chcieliśmy również mieć pewną formę automatyzacji, więc zbudowaliśmy i używamy wielu narzędzi do modyfikacji kodu, aby wspomóc ten proces (które wypuszczamy jako część Hacka).

Nie martw się, twoje PHP jest bezpieczne!

HVM jest wciąż PHP runtime, i zamierzamy utrzymać go w ten sposób. W rzeczywistości, ciężko pracujemy nad tym, aby osiągnąć zgodność z PHP-5. Jednym z priorytetów HHVM jest uruchomienie niezmodyfikowanego kodu źródłowego PHP-5, zarówno dla społeczności, jak i dlatego, że wewnętrznie polegamy na bibliotekach PHP innych firm.

HVM jest teraz runtime, który obsługuje zarówno PHP, jak i Hacka, więc możesz zacząć korzystać z nowych funkcji Hacka stopniowo.

Zabaw się z Hackiem!

Jesteśmy zachwyceni, że możemy udostępnić zarówno Hacka, jak i narzędzia, których możesz użyć do automatycznej konwersji swojej bazy kodu. To jest tylko pierwszy krok i jesteśmy oddani dalszemu rozwijaniu tego oprogramowania, aby uczynić rozwój jeszcze łatwiejszym zarówno dla naszych inżynierów, jak i dla szerszej społeczności. Wartość Hacka nie jest *nie* ograniczona do dużych projektów: z informacją o typie, dobrymi komunikatami o błędach i szybką informacją zwrotną, małe bazy kodu mogą również czerpać korzyści z Hacka.

W przyszłym miesiącu, przedstawimy również język na Hack Developer Day w kampusie Facebooka w Menlo Park i mamy nadzieję, że zobaczymy się tam osobiście lub online.

Będziemy wdzięczni za Wasze opinie na temat naszej dotychczasowej pracy i zapraszamy wszystkich do uczestnictwa w społeczności HHVM i Hacka.

Podziękowania

Jest wiele osób, które przyczyniły się do rozwoju Hack.

Główny zespół Hack składa się z Julien Verlaguet, Joel Beales, Eugene Letuchy, Gabriel Levi, Joel Marcey, Erik Meijer, Alok Menghrajani, Bryan O’Sullivan, Drew Paroski, James Pearce, Joel Pobar i Joshua Van Dyke Watzman.

Szczególne podziękowania kierujemy do naszych pierwszych użytkowników za dostarczenie cennych informacji zwrotnych, które sprawiły, że język stał się lepszy: James Miller, Simon Welsh, Nils Adermann, Fabien Potencier i Alexander Mols.

Hack jest napisany głównie w OCamlu. Chcielibyśmy podziękować zespołowi Gallium (INRIA) za rozwój języka OCaml oraz zespołowi Ocsigen (CNRS – Uniwersytet Paris Diderot – INRIA) za rozwój części js_of_ocaml w Ocsigen.

Oraz, oczywiście, dziękujemy wszystkim innym, którzy pomogli uczynić Hacka językiem, jakim jest dzisiaj. Ta lista jest zbyt wyczerpująca jak na wpis na blogu, ale wiecie kim jesteście.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.