Halo, Habr! Saya menyampaikan kepada Anda terjemahan laporan Alexander Kuzmenko dari Konferensi Sumber Terbuka Hong Kong (14-15 Juni) baru-baru ini (2019).

Sebelum bergabung dengan Haxe Foundation sebagai pengembang kompiler Haxe, Alexander secara profesional terlibat dalam pemrograman PHP selama sekitar 10 tahun, sehingga ia mengetahui subjek laporan.

Pengantar kecil tentang apa itu Haxe adalah seperangkat alat lintas platform untuk membuat perangkat lunak, yang meliputi:
- kompiler yang, tergantung pada platform target, baik menerjemahkan kode Haxe sumber ke dalam kode sumber dalam bahasa pemrograman lain (C ++, PHP, Java, C #, JavaScript, Python, Lua), atau mengkompilasi langsung ke kode byte mesin virtual (JVM, neko , HashLink, Flash)
- perpustakaan standar diimplementasikan untuk semua platform yang didukung
- Haxe juga menyediakan alat untuk berinteraksi dengan kode yang ditulis dalam bahasa platform target.
- pengelola perpustakaan standar - haxelib

Dukungan PHP di Haxe muncul sejak lama - pada tahun 2008. Dalam versi Haxe hingga 3.4.7 inklusif, PHP 5.4 dan lebih tinggi didukung, dan dimulai dengan versi keempat, Haxe mendukung PHP versi 7.0 dan lebih tinggi.

Anda mungkin bertanya: mengapa pengembang PHP harus menggunakan Haxe?
Alasan utama untuk ini adalah kemampuan untuk menggunakan logika yang sama pada server dan klien.
Pertimbangkan contoh ini: Anda memiliki server yang ditulis dalam PHP menggunakan kerangka Laravel, dan beberapa klien yang ditulis dalam JavaScript, Java, C #. Dalam hal ini, untuk memproses interaksi jaringan antara server dan klien (logikanya pada dasarnya sama), Anda perlu menulis 4 implementasi untuk setiap bahasa yang digunakan. Tetapi dengan Haxe, Anda dapat menulis kode protokol jaringan sekali dan kemudian mengkompilasi / menerjemahkannya di bawah platform yang berbeda, menghemat banyak waktu untuk hal ini.

Berikut contoh lain - aplikasi game - bentrokan Clash of Clans. Alexander berpartisipasi dalam pengembangan permainan seperti itu: servernya ditulis dalam PHP, klien seluler dalam C # (Xamarin), dan klien peramban dalam JavaScript menggunakan kerangka kerja Phaser. Di klien dan server, satu logika diproses - yang disebut "pertempuran", yang menghitung perilaku unit pemain di lokasi. Awalnya, kode tempur ditulis untuk masing-masing platform secara terpisah. Namun seiring berjalannya waktu (dan proyek ini telah berkembang selama sekitar 5 tahun), perbedaan telah menumpuk dalam perilakunya di server dan pada klien. Ini karena fakta bahwa itu ditulis oleh orang yang berbeda, yang masing-masing menyadarinya dengan caranya sendiri. Karena itu, tidak ada cara yang dapat diandalkan untuk mendeteksi curang, karena logika di server berperilaku sangat berbeda dari pada klien, sebagai akibatnya, pemain yang jujur ββjuga menderita. server dapat menghitungnya sebagai curang dan tidak menghitung hasil pertempuran yang jujur.
Pada akhirnya, diputuskan untuk mentransfer pertempuran ke Haxe, yang memungkinkan untuk sepenuhnya menyelesaikan masalah dengan curang, karena sekarang logika pertempuran berperilaku sama di semua platform. Selain itu, keputusan ini memungkinkan untuk mengurangi biaya pengembangan lebih lanjut dari sistem tempur, seperti sekarang sudah cukup untuk satu programmer yang akrab dengan Haxe, bukannya tiga, yang masing-masing akan bertanggung jawab untuk platformnya.

Bagaimana Haxe dan PHP berbeda satu sama lain? Secara umum, sintaks Haxe tampaknya bukan sesuatu yang asing bagi programmer PHP. Ya, ini berbeda, tetapi dalam banyak kasus akan sangat mirip dengan PHP.
Slide menunjukkan perbandingan kode untuk menampilkan string di konsol. Di Haxe, kode tersebut terlihat hampir sama, kecuali bahwa untuk bekerja dengan fungsi PHP Anda perlu mengimpornya (lihat baris pertama).

Dan ini adalah bagaimana kode PHP yang dihasilkan terlihat dibandingkan dengan yang ditulis secara manual.
Kompiler Haxe secara otomatis menambahkan blok komentar ke kode yang menjelaskan tipe argumen fungsi dan tipe pengembalian, sehingga kode yang dihasilkan dapat dihubungkan ke proyek PHP dan pelengkapan otomatis akan berfungsi dengan baik untuk itu.
Mari kita lihat beberapa perbedaan signifikan dalam sintaksis Haxe dan PHP.

Mari kita mulai dengan perbedaan dalam sintaks fungsi anonim (menggunakannya sebagai contoh untuk mengurutkan array).
Slide menunjukkan fungsi anonim yang menangkap dan mengubah nilai dari desc
variabel lokal. Di PHP, Anda perlu menentukan secara eksplisit variabel mana yang tersedia di tubuh fungsi anonim. Selain itu, untuk dapat mengubah nilai variabel, Anda harus menambahkan &
di depan namanya.
Di Haxe, ini tidak lagi diperlukan. kompiler itu sendiri menentukan variabel mana yang Anda akses. Selain itu, fungsi panah (bentuk singkat untuk menggambarkan fungsi anonim) muncul di Haxe 4, dengan menggunakan yang kita dapat mempersingkat contoh kita dengan mengurutkan array menjadi hanya satu baris.

Perbedaan lain dalam sintaks adalah perbedaan dalam deskripsi konstruksi kontrol switch
. Di PHP, switch
bekerja sama dengan di C. Di Haxe, ini bekerja secara berbeda:
- pertama, saklar tidak menggunakan kata kunci
break
- kedua, Anda dapat menggabungkan beberapa kondisi menggunakan
|
(Daripada menduplikasi kata kunci case
) - ketiga, Haxe menggunakan pencocokan pola untuk
switch
. Jadi, misalnya, Anda dapat menerapkan switch
ke array, dan dalam kondisi Anda dapat menentukan tindakan tergantung pada isi array (tanda _
berarti bahwa nilai ini tidak mengganggu kita dan bisa berupa apa saja). Kondisi [1, _, 3]
akan terpenuhi jika array terdiri dari tiga elemen, sedangkan elemen pertama adalah 1, yang ketiga adalah 3, dan nilai yang kedua adalah apa saja.

Di Haxe, semuanya adalah ekspresi, dan ini memungkinkan Anda untuk menulis kode yang lebih ringkas. Anda dapat mengembalikan nilai dari try
/ catch
, if
atau switch
tanpa menggunakan kata kunci return
di dalam konstruksi ini. Dalam contoh di atas dengan try
/ catch
kompiler βtahuβ bahwa Anda ingin mengembalikan beberapa nilai dan dapat meneruskannya dari konstruk ini.

PHP secara bertahap bergerak ke arah pengetikan yang lebih kuat, tetapi Haxe sudah memiliki pengetikan statis yang kuat!
Dalam contoh di atas, kami menetapkan variabel s
nilai yang diperoleh dari functionReturnsString()
, yang mengembalikan string. Jadi, tipe variabel s
adalah string. Dan jika Anda mencoba meneruskannya ke fungsi giveMeInteger()
, yang giveMeInteger()
integer sebagai argumen, kompiler Haxe akan melempar kesalahan tentang tipe mismatch.
Contoh ini juga menunjukkan fitur penting lain dari Haxe - inferensi tipe - kemampuan kompiler untuk secara independen menentukan jenis variabel tergantung pada nilai apa yang diberikan.

Untuk programmer, ini berarti bahwa dalam kebanyakan kasus secara eksplisit menentukan jenis variabel adalah opsional. Jadi dalam fungsi isSmall()
di atas, kompiler menentukan bahwa tipe argumen a
adalah integer, karena pada baris pertama dari fungsi body, kita membandingkan nilai a
dengan integer. Lebih lanjut, kompiler, berdasarkan pada fakta bahwa pada baris kedua dari fungsi tubuh kita mengembalikan true
, menentukan bahwa tipe pengembalian adalah nilai Boolean. Dan karena Karena kompiler telah menentukan jenis nilai pengembalian, maka setelah upaya lebih lanjut untuk mengembalikan jenis lain dari fungsi, ia akan melempar kesalahan jenis ketidakcocokan.

Di Haxe, tidak seperti PHP, tidak ada konversi tipe otomatis. Misalnya, dalam PHP dimungkinkan untuk mengembalikan string dari suatu fungsi yang ditunjukkan bahwa ia mengembalikan integer, dalam hal ini, ketika skrip dieksekusi, string akan dikonversi ke angka (tidak selalu berhasil). Dan di Haxe, kode yang sama tidak dapat dikompilasi - kompiler akan melempar kesalahan tipe ketidakcocokan.

Fitur lain dari Haxe adalah sistem tipe canggihnya, yang meliputi:
- tipe fungsi, terdiri dari tipe argumen fungsi dan tipe kembali
- tipe umum (parameterisasi) (misalnya, ini termasuk array yang jenis nilai yang disimpan digunakan sebagai parameter)
- jenis yang disebutkan
- tipe data aljabar umum
- tipe struktur anonim memungkinkan Anda untuk mendeklarasikan tipe objek tanpa mendeklarasikan kelas
- tipe data abstrak (abstraksi atas tipe yang ada, tetapi tanpa kehilangan kinerja saat runtime)
Semua jenis ini dikonversi ke kelas PHP selama kompilasi.

Salah satu fitur pembeda utama Haxe adalah metaprogramming (dalam Haxe disebut macro), yaitu, kemampuan untuk secara otomatis menghasilkan kode sumber dari suatu program.
Makro dieksekusi pada saat penyusunan program dan ditulis pada Haxe biasa.
Macro memiliki akses penuh ke pohon sintaksis abstrak, yaitu, mereka dapat membaca (mencari ekspresi yang diperlukan di dalamnya) dan memodifikasinya.
Makro dapat menghasilkan ekspresi, memodifikasi tipe yang ada, dan membuat yang baru.

Dalam konteks PHP, makro misalnya dapat digunakan untuk routing. Katakanlah Anda memiliki kelas router sederhana yang mengimplementasikan metode untuk menampilkan halaman dengan pengenalnya, serta metode untuk log off. Menggunakan makro, Anda bisa membuat kode untuk metode route()
, yang, berdasarkan permintaan http, akan mengarahkannya ke metode yang sesuai dari kelas Router
. Dengan demikian, tidak perlu secara manual menulis jika untuk panggilan ke masing-masing metode kelas ini (makro akan melakukan ini secara otomatis ketika mengkompilasi proyek dalam PHP). Perhatikan bahwa kode yang dihasilkan tidak menggunakan refleksi, tidak memerlukan file konfigurasi khusus, atau trik tambahan lainnya, sehingga akan bekerja dengan sangat cepat.

Contoh lain dari penggunaan makro adalah pembuatan kode untuk parsing dan validasi JSON. Misalnya, Anda memiliki kelas Data
yang objeknya harus dibuat berdasarkan data yang diperoleh dari JSON. Ini dapat dilakukan dengan menggunakan makro, tetapi karena makro memiliki akses ke struktur kelas Data
, selain parsing, Anda dapat menghasilkan kode untuk validasi JSON dengan menambahkan pengecualian melempar dengan tidak adanya bidang atau ketidakcocokan tipe data. Dengan demikian, Anda dapat yakin bahwa aplikasi Anda tidak akan melewatkan data yang salah yang diterima dari pengguna atau dari server pihak ketiga.
Penting juga menyebutkan fitur penting dari implementasi beberapa tipe data untuk platform PHP, seperti jika Anda tidak memperhitungkannya, maka Anda dapat menghadapi konsekuensi yang tidak menyenangkan.

Dalam PHP, string adalah biner aman , jadi dalam PHP, jika Anda tidak memerlukan dukungan Unicode, metode untuk bekerja dengan string bekerja sangat cepat.
Di Haxe, dimulai dengan versi keempat, string mendukung Unicode, jadi ketika mengompilasinya dalam PHP, metode dari modul akan digunakan untuk bekerja dengan string multibyte mbstring, yang berarti akses lambat ke karakter sewenang-wenang dalam string, perhitungan lambat dari panjang string.
Oleh karena itu, jika Anda tidak memerlukan dukungan Unicode, maka Anda dapat menggunakan metode kelas php.NativeString
untuk bekerja dengan string, yang akan menggunakan string "asli" dari PHP.

Slide di sebelah kiri menunjukkan kode PHP yang menggunakan kedua metode yang mendukung Unicode dan tidak.
Di sebelah kanan adalah kode Haxe yang setara. Seperti yang Anda lihat, jika Anda memerlukan dukungan Unicode, Anda harus menggunakan metode kelas String
, jika tidak, maka metode kelas php.NativeString
.

Poin penting lainnya adalah bekerja dengan array.
Dalam PHP, array diteruskan oleh nilai, dan array juga mendukung tombol angka dan string.
Di Haxe, array dilewatkan oleh referensi dan hanya mendukung kunci numerik (jika kunci string diperlukan, maka kelas Map
harus digunakan untuk ini di Haxe). Juga, "lubang" dalam indeks tidak diperbolehkan dalam array Haxe (indeks harus terus menerus).
Perlu juga dicatat bahwa menulis ke array dengan indeks di Haxe sangat lambat.

Berikut adalah kode untuk memetakan array menggunakan fungsi panah. Seperti yang Anda lihat, kompiler Haxe cukup aktif mengoptimalkan kode PHP yang diterima pada output: tidak ada fungsi anonim dalam kode yang dihasilkan, alih-alih kode tersebut diterapkan dalam satu lingkaran ke setiap elemen array. Selain map()
pengoptimalan ini juga berlaku untuk metode filter()
.
Juga, jika perlu, Anda bisa menggunakan kelas php.NativeArray
dan metode PHP yang sesuai untuk bekerja dengan array di Haxe.

Objek anonim diimplementasikan menggunakan kelas HxAnon
, yang mewarisi dari kelas StdClass
dari PHP.

Dalam PHP, StdClass
adalah kelas ke instance yang segala sesuatu yang kita coba konversi menjadi objek dikonversi. Dan itu akan ideal untuk mengimplementasikan objek anonim, jika bukan karena satu fitur dari spesifikasi mereka: di Haxe, mengakses bidang yang tidak ada dari objek anonim harus mengembalikan null
, dan dalam PHP ini memberikan peringatan. Karena itu, saya harus mewarisi dari kelas standar dari PHP dan menambahkan metode ajaib, yang ketika mengakses properti yang tidak ada, mengembalikan null
.

Haxe dapat berinteraksi dengan kode yang ditulis dalam PHP. Untuk melakukan ini, ada fitur berikut (mirip dengan kemungkinan berinteraksi dengan kode JavaScript):
- externs
- embed kode php langsung dalam kode haxe
- kelas khusus dari paket
php.*
php.Syntax
- untuk konstruksi PHP khusus yang tidak ada di Haxephp.Global
- untuk fungsi global PHP asliphp.Const
- untuk konstanta global PHP asliphp.SuperGlobal
- untuk variabel PHP superglobal yang dapat diakses dari mana saja ( $_POST
, $_GET
, $_SERVER
, dll.)

Karena PHP menggunakan model OOP klasik, kemudian menulis eksternal untuk itu adalah proses yang cukup sederhana. Faktanya, externs untuk kelas PHP hampir merupakan "terjemahan" literal di Haxe, dengan pengecualian beberapa kata kunci.
Sebagai contoh, kode eksternal untuk kelas PHP dari slide di atas akan terlihat seperti ini:

Konstanta dari kelas PHP "berubah" menjadi variabel statis dalam kode Haxe (tetapi dengan penambahan tag meta khusus).
Variabel statis $useBuiltinEncoderDecoder
menjadi variabel statis useBuiltinEncoderDecoder
.
Ini menunjukkan bahwa externs untuk kelas PHP dapat dibuat secara otomatis (Alexander berencana untuk mengimplementasikan generator eksternal tahun ini).

Untuk memasukkan kode PHP, modul php.Syntax
khusus php.Syntax
. Kode yang ditambahkan dengan cara ini tidak tunduk pada konversi atau optimisasi apa pun oleh kompiler Haxe.
Selain php.Syntax
, Haxe masih memiliki kemampuan untuk menggunakan kode yang tidak diketik .

Perlu disebutkan juga fitur-fitur Haxe yang tidak ada dalam PHP:
- properti nyata dengan metode baca dan tulis
- bidang dan variabel read-only
- ekstensi statis
- meta tag yang dapat digunakan untuk membubuhi keterangan bidang dan yang dapat dibaca di makro. Dengan demikian, tag meta terutama digunakan untuk metaprogramming.
- Keamanan kosong (fungsi eksperimental)
- kompilasi bersyarat, yang memungkinkan Anda untuk mengaktifkan / menonaktifkan bagian dari kode yang mungkin tersedia, misalnya, dalam versi debug aplikasi
- Kompiler Haxe menghasilkan kode PHP yang sangat dioptimalkan yang dapat berjalan beberapa kali lebih cepat daripada kode PHP yang ditulis secara manual.
Informasi lebih lanjut tentang Haxe dan fitur-fiturnya tersedia di panduan resmi .