DEV Community

Codlook
Codlook

Posted on

LOOK 1'den LOOK 2'ye: neler değişti


LOOK, web için yapılmış kendi dilimiz. LOOK 1 bugün yayında olan sürüm (1.0.x). LOOK 2
v2` dalında geliştiriliyor ve henüz yayınlanmadı. Bu yazı ikisi arasındaki farkı anlatıyor: neyi, neden değiştirdik ve LOOK 1 ile yazılmış bir uygulama için bu ne anlama geliyor.

Kısa cevap şu: LOOK 2 yeni özellik yığını değil. LOOK 1'de "bazen öyle, bazen böyle" davranan yerlerin her birine tek bir cevap veriyor ve sessizce yanlış sonuç üreten davranışları ya düzeltiyor ya da hataya çeviriyor.

Neden gerekti?

LOOK 1'i gerçek uygulamalarla sınadıkça üç tür sorun tekrar tekrar karşımıza çıktı:

  • Paylaşılan veri. Diziler ve map'ler referansla paylaşılıyordu. Bir fonksiyona verdiğiniz dizi, o fonksiyon içinde değişince sizin elinizdeki de değişiyordu. Web sunucusunda bunun en kötü hali, bir isteğin verisinin başka bir isteğe sızmasıydı. 1.0.3, 1.0.4 ve 1.0.5 sürümlerinin üçü de bu sınıftan hataları tek tek yamadı.
  • İki motor, iki davranış. LOOK'ta hızlı bir sanal makine (VM) ve onun yanında bir yorumlayıcı var. Aynı kod bazı durumlarda ikisinde farklı sonuç veriyordu: fazla argümanla çağrı birinde hata, diğerinde sessizce kabul; blok içinde tanımlanan değişken birinde görünür, diğerinde değil.
  • Sessiz geri düşüş. VM bir şeyi çalıştıramadığında uygulama haber vermeden yorumlayıcıya geçiyordu. Sonuç doğruydu ama yavaştı ve gerçek hataları gizliyordu.

LOOK 2'nin ölçütü basit: her sorunun tek bir cevabı olsun ve hiçbir şey gizli kalmasın.

1. Diziler, map'ler ve struct'lar artık değer

En büyük değişiklik bu.

php
$a = [1, 2, 3]
$b = $a
$b[0] = 9 # LOOK 2: $a hâlâ [1, 2, 3]. LOOK 1: $a da değişirdi.

Atama, fonksiyona verme ve fonksiyondan döndürme, alan tarafa kendi değerini verir. Bu her derinlikte geçerli.

Bunun bedeli kopyalama değil: atamada kopya yapılmaz. Değer yalnızca hâlâ paylaşılırken üzerine yazıldığında kopyalanır. Büyük bir diziyi yalnızca okuyan bir fonksiyona vermek hiçbir şeye mal olmaz.

Kırılan kalıp, parametresini değiştirip geri döndürmeyen fonksiyondur:

php
function add_total($order) { $order["total"] = 42 }
add_total($o) # LOOK 1: $o'da "total" var. LOOK 2: $o değişmedi.

Doğrusu, değeri döndürüp atamak:

php
function add_total($order) {
$order["total"] = 42
return $order
}
$o = add_total($o)

Bu, sessizce geçebilecek tek değişiklik olduğu için raporlanıyor: dosya yüklenirken bir uyarı satırı çıkar, lk --check aynı bulguyu hata olarak verir ve bir derlemeyi durdurabilir.

Aynı kuralın iki sonucu daha var:

  • == içeriği karşılaştırır. İki dizi, map ya da struct aynı şeyi tutuyorsa eşittir. LOOK 1'de diziler ve map'ler için sonuç her zaman false idi.
  • Paylaşmak için tutamaç kullanılır. Kanallar, WebSocket/SSE bağlantıları ve veritabanı bağlantıları değer değil tutamaçtır; kopyası aynı şeye işaret eder. İstekler arasında bilinçli paylaşımın yolu budur.

2. Closure değeri yakalar

Bir closure, yakaladığı şeyin oluşturulduğu andaki değerini alır ve onu değiştiremez.

php
$n = 1
$f = fn() => $n
$n = 2
$f() # LOOK 2: 1. LOOK 1: 2.

Yakalanan değişkene closure içinden yazmak (atama, +=, ++, push) artık yükleme hatasıdır; program başlamaz. Yeni değeri döndürüp dışarıda atarsınız. Sonradan dışarıda yapılan değişikliğin closure'a yansımaması ise sessiz bir farktır; lk --check bu yerleri satır numarasıyla listeler.

LOOK 1'deki istekler arası sızıntıların arkasındaki kalıp buydu: closure'ın paylaşılan bir değişkeni değiştirmesi. LOOK 2'de bu kalıp yazılamıyor.

3. Struct'lar: tipli alanlar, sabit şekil

plaintext
struct User {
name string
age int = 18
score ?float # null olabilir
tags array
}

  • Tek yazım biçimi var: ad tip, isteğe bağlı = varsayılan. LOOK 1'in iki eski yazımı artık ayrıştırma hatası.
  • Tipler denetlenir, hem oluştururken hem her atamada.
  • Şekil sabittir. Bildirilmemiş bir alanı okumak ya da yazmak hatadır. LOOK 1 okumada null döndürür, yazmada alanı sessizce eklerdi.
  • Varsayılansız alan sıfır değeriyle başlar (int 0, string "", dizi boş). LOOK 1'de null idi.
  • Struct dizi değildir. count($s) ve array:: fonksiyonları struct üzerinde hatadır.
  • Bir struct bir kez, dosyanın en üst düzeyinde bildirilir.

4. Okuma, çağrı ve kapsam: tek kural

[...] ile okuma. Olmayan anahtar null verir. null'dan okumak null verir, bu yüzden $row["address"]["city"] ?? "" zinciri özel bir kurala ihtiyaç duymaz. Ama bir string'i ya da sayıyı indekslemek hatadır: bu eksik değer değil, yanlış tiptir. LOOK 1'de bu, kodun hangi motorda çalıştığına göre değişiyordu.

Çağrı. Bir fonksiyon, bildirdiği argümanlarla çağrılır. Fazla ya da eksik argüman hatadır. LOOK 1'in varsayılan motoru fazlayı atıyor, eksiği null yapıyordu.

Kapsam. Blok içinde ilk kez atanan değişken blok bitince yok olur; bu artık dosyanın en üst düzeyinde de geçerli.

Küçük eklemeler. $count["views"]++ ve ++$cart.items artık çalışıyor. ++ ya da -- ile başlayan satır kendi başına bir ifadedir.

5. Web tarafı

  • Rota parametreleri ada göre verilir. route("GET", "/c/{id}/{slug}", function($slug) {...}) LOOK 1'de $slug'a sessizce id'yi veriyordu. Artık her parametre aynı adlı yol parametresini alır; rotada olmayan bir ad uygulamayı başlangıçta durdurur.
  • Olmayan bir fonksiyonu çağıran rota uygulamayı başlangıçta durdurur. string::uper(...) gibi bir yazım hatası LOOK 1'de ilk isteğe kadar fark edilmiyordu.
  • İş işleyicisi true ya da false döndürür ve yeniden deneme bekler. LOOK 1'de return yazmayı unutmak "başarısız" sayılıyor ve iş hemen yeniden çalışıyordu; bir e-posta üç kez gidebiliyordu. Artık yeniden denemeler 30, 60, 120 saniye arayla yapılır.
  • İş işleyicileri ve zamanlayıcılar kendi isteklerinde çalışır. Bir rotanın içinden başlatılan işleyici artık o isteğin parametrelerini okuyamaz, yanıtını değiştiremez.
  • Varsayılan 404 düz metindir.
  • WebSocket/SSE bağlantılarında yerleşik sınır yok. Sınırı işletim sistemi koyar. (Bu, 1.0.15 ile LOOK 1'e de geldi.)

6. Motor: her şey VM'de

LOOK 1'de web uygulamasının bazı parçaları her zaman yorumlayıcıda çalışıyordu: WebSocket ve SSE işleyicileri, zamanlayıcılar, iş işleyicileri, kendi dosyalarını dahil eden komut satırı betikleri. LOOK 2'de bunların hepsi VM'de.

Hedef tek motor: VM bir uygulamayı derleyemiyorsa uygulama başlamaz ve nedenini söyler. Yorumlayıcı yalnızca testlerde karşılaştırma için kalır. Bu iş sürüyor; bugün lk --vm-report çekirdek modüllerdeki 228 fonksiyonun hepsinin VM'de bulunduğunu doğruluyor.

Ölçtüklerimiz

Aşağıdaki rakamlar bu bilgisayarda, Docker içinde ölçüldü. Her biri tek bir senaryo içindir; genel bir "şu kadar kat hızlı" iddiası değildir.

Ölçüm LOOK 1 LOOK 2
Açık WebSocket bağlantısı başına sunucu belleği yaklaşık 38 KB 0,89 KB
700 bin açık WebSocket 400 binde 11 GB, belleği yetmedi 618 MB, hepsi açık
Döngü ağırlıklı bir iş işleyicisi 4,2 sn 0,08 sn
Dosya dahil eden, döngü ağırlıklı komut satırı betiği 3,7 sn 0,07 sn
Şablon ağırlıklı sayfa, uçtan uca 2,7 bin istek/sn 12 bin istek/sn

Bağlantı ölçümü yalnızca boşta duran bağlantıları kapsıyor ve tek koşudur; mesaj trafiği altında ölçülmedi.

LOOK 1 uygulamanız için ne anlama geliyor?

LOOK 2, LOOK 1 ile uyumlu değil; bu bilinçli bir karar. Ama değişikliklerin çoğu kendini belli eder:

  • Yükleme hatası: program başlamaz, mesaj satırı söyler. (Eski struct yazımı, closure içinden yazma, rotada olmayan parametre adı.)
  • Çalışma zamanı hatası: ifade hata verir, mesaj nedeni söyler. (Yanlış argüman sayısı, bildirilmemiş alan, string'i indeksleme.)
  • Sessiz: program çalışır ama farklı sonuç verir. Dikkatle okunması gerekenler bunlar: değer semantiği, closure'ın değeri yakalaması, ==, varsayılansız alanların sıfır değeri, rota parametrelerinin ada göre verilmesi.

Geçişte ilk adım, uygulamanın her dosyasında lk --check çalıştırmak. Parametresini değiştirip döndürmeyen fonksiyonları, sonradan değişen yakalanmış değişkenleri ve yanlış argüman sayılarını satır numarasıyla listeler.

Her değişikliğin tam listesi, ne göreceğiniz ve yerine ne yazacağınızla birlikte docs/migrating-to-look-2.md dosyasında. O dosya her değişiklikle aynı commit'te güncelleniyor.

Şu an neredeyiz?

  • LOOK 1 yayında ve güvenlik düzeltmeleri almaya devam ediyor; son sürüm 1.0.15.
  • LOOK 2 v2 dalında. Yukarıdaki dil kuralları yerinde ve her biri iki motorda testli. Yayın için kalan iş, kurulumun da tamamen VM'de çalışması, yani tek motor hedefinin tamamlanması.
  • LOOK 2, uygulama tamamen VM'de çalıştığında yayınlanacak. `

Top comments (0)