fatiherikli

Fil için bir back-end servisi olmadan browser üzerinde kod yazmaya olanak sağlayan basit bir IDE diyebiliriz. Anlık olarak kod yazıp çıktısını alabiliyor, ve çıktıyı okunabilirlik açısından görselleştirebiliyor. Şimdilik Python, Ruby, Javascript ve Brainfuck dillerini destekliyor. Ayrıca rengi mor.

Neden yaptım?

Fil bir haftasonu projesiydi. Böyle bir şeye girişmemin sebebi ise kız arkadaşım. Özetlemem gerekirse; kendisi bilgisayar ile yakından alakası olmayan bir alanda. Bir programlama geçmişi yok, ancak kendi alanında hesaplamalar ve ufak uygulamalar yapmak için Python öğrenmeye çalışıyor. Başlangıç noktamız (proje için) burasıydı.

Öğrendiklerini rahatça deneyebilmesi ve kaydedebilmesi için bütünleşik bir araç gerekmişti.

Python shell'den biraz daha gelişmiş, tam donanımlı bir IDE kadar gelişmiş olmayan bir araç yeterli olacaktı. Mümkünse kurulumu zor olmayan ve hafif bir şey olması gerekiyordu bir de. Doğru düzgün çalışan ve bu ihtiyaçlarımızı karşılayabilecek bir şey bulamadık. Aslında vardı, ama hepsi çok çirkindi. Hiçbirini kullandıramadım ve kendim kolları sıvamaya karar verdim.

Browser üzerinde çalışan, yazdığı kodun çıktısını aynı anda ve görselleştirilmiş bir şekilde veren bir şey yapmaya çalıştım. Terminalden ve siyah/beyaz ekranlardan biraz korktuğu için rengini mor yaptım. Adını da fil koydu.

Umuyoruz ki programlamaya yeni başlayan ve bilgisayar ile alakasız alanlarda okuyan başka kişiler için motive edici ve kullanabildikleri bir araç olmuştur.

Nasıl çalışıyor?

Fil ilk önce sadece Python çalıştırabiliyordu. Hatta logosundaki mavi ve turuncu noktalar Python'ın renkleri. Javascript ile implement edilmiş bir Python interpreter bakındım. Birkaç çözüm vardı, ama en kullanılabilir Skulpt ve Brython olmuştu. Brython'a göre Skulpt, kullanımı daha basit ve API'ı daha düzgün bir kütüphaneyi. Bu yüzden Skulpt'ı seçtim.

Skulpt'ı entegre ettikten sonra interpreter kısmını biraz daha soyutlaştırarak Python'dan başka dillerini destekleyebilmesi için refactor ettim. Skulpt'ın Python'ı yorumlayabildiği gibi, aynı şekilde Ruby için de aynı işi yapan bir interpreter vardı; Opal. Soyutlaştırmayı yaptıktan sonra Fil Python ve Ruby IDE'si olmuştu artık.

Web workers

Projeyi yayınlamak üzereyken bir bug farkettim. Skulpt ve Opal birlikte kararlı çalışmıyolardı. Tamamen farklı namespace üzerindeydiler, ama yine de tahmin ediyorum ki ikisi de global space'te bir şeyleri paylaşamıyolardı. Karşılaştığım bug, Opal'ı dahil ettiğimde Skulpt tarafında dictionary'leri ekrana çizdiremememdi.

Bunu ilk önce Opal'ı, ya da Skulpt'ı düzelterek çözmeye çalıştım, ancak bir yere varamadım. Bunu zaten yapmak istermiyordum, çünkü ikisi da çok büyük projelerdi, içindan çıkamama ihtimalim vardı.

Global namespace'i interpreter'lardan izole etmek için Web Worker'ları kullanmaya karar verdim. İzole etmemin dışında ayrıca hem interpreter çalışırken main thread'i kilitlemeyecek, hem de eğer kullanıcı sadece Python yazıyorsa, browser üzerinde sadece Skulpt yüklenecekti. Kısacası web worker'lar bunun için çok yerinde bir karar olmuştu. Interpreter'ları worker'lara taşıdıktan bir problem kalmadı. Ayrıca yeni bir dil eklemek de çok daha kolaylaştı artık.

İşte fil'de kullanılabilecek örnek bir interpreter worker'ı:

// workers/markdown.js 
let sendMessage = (name, message) => {
  self.postMessage(JSON.stringify({
    type: name,
    data: message
  }));
}

let run = source => {
  var parser = new Markdown(),
      output;
  try {
    output = parser.parse(source)
    sendMessage('stdout', output);
  } catch (e) {
    sendMessage('stderr', {
      exception: 'ParseError',
      description: String(e)
    });
  }
  sendMessage('exit');
}

self.addEventListener('message', (e) => run(e.data));

Worker'lara mesaj olarak gelen source code yorumlanırken satır satır stdout tipinde yanıt gönderilip, çalışan programın sonuna gelindiğinde ise exit mesajı ile bildiriliyor. Eğer program çalışırken bir hata olmuşsa Fil üzerinde bunu gösterebilmek için stderr mesaj tipiyle hata detayları gönderiliyor.

Neler kullanıyor?

Son 1 senedir React ile oldukça haşır neşir oldum, ve bu proje için de React kullandım. Özellikle fil'de konsol çıktıları için React iyi bir çözüm oldu diyebilirim. React'in getirdiği Virtual DOM sayesinde yeniden çalıştırıla bir kodun çıktısı baştan render edilmek yerine, sadece değişen kısım render ediliyor.

Component Hiearchy

Temel component hiyerarşisinin taslağını çizmeye çalıştım. Fil'in arayüzü birbirinden bağımsız bu büyük component'lar ve bunların içindeki alt component'lardan oluşuyor.

Uygulama mimarisi açısından bu sefer Flux yerine Redux'ı denemek istedim. Redux'tan bana ilk defa Burak bahsetmişti, ve oldukça ilgi çekici gelmişti. Kitap gibi bir dökümantasyonu var ve okuması çok eğlenceli, mutlaka bakmanızı tavsiye ederim.

Redux aslında tam olarak Flux'un bir karşılığı değil. Kendi deyimiyle Redux javascript uygulamaları için bir state container. Redux ile geliştirdiğiniz uygulamanın state'i tamamen immutable bir şekilde, reducer adını verdikleri saf fonksiyonlarıyla ilerliyor. Tüm state tek bir noktada saklanıyor, ve bu state'in taşınabilirliği ve saklanması açısından büyük bir avantaj.

(previousState, action) => newState

Redux uygulamaları tamamen yukarıdaki gibi akışa göre ilerlemekte. Bu bir reducer. Kullanıcının yaptığı her davranış'a action deniyor. Her bir action bütün reducer'lardan geçirilerek yeni state oluşturuluyor. Uygulama arayüzü ise bu state'i ekrana çiziyor.

Redux, React'tan bağımsız bir proje olarak ilerliyor. React ile kullanmak için redux-react paketini kullanıyoruz. Ayrıca redux state'ini localStorage üzerinde tutmek için redux-localstorage kullanıldı.

React ve Redux dışında kullanılan diğer şeyler şöyle:

Not aldığım şeyler şimdilik bu kadar, yazdığınız yorumlara göre yazıyı tekrar güncelleyebilirim.

Ayrıca projenin sahibi, isim, ve renk kaynağı guinea-pig yavrusuna desteği için çok teşekkürler.

Bağlantılar:

comments powered by Disqus