2 puan yazan GN⁺ 2023-11-11 | 1 yorum | WhatsApp'ta paylaş
  • Bir Ruby backend geliştiricisi, Elixir’i ana dili olarak kullanan bir şirkete katıldıktan sonra, Ruby’den etkilenmiş söz dizimi sayesinde Elixir/Erlang deneyimi olmasa da nispeten hızlı uyum sağladı
  • Elixir, Ruby gibi söz dizimsel eğlence ve DSL dostu bir yapı sunarken; sınıf, instance ve kalıtım içermeyen değişmez fonksiyonel modeliyle durum yönetimi yükünü azaltır
  • Ruby DSL’leri çalışma zamanında nesneleri ve metotları dinamik olarak tanımlamaya dayanırken, Elixir DSL’leri derleme zamanı makrolarıyla çalışma zamanı kodu üretir ve hataları daha erken ortaya çıkarır
  • Pipeline söz dizimi, with ifadesi ve {:ok, result} biçimindeki Result tuple’ları, normal akış ile kurtarılabilir hata işlemeyi ayırmak için kullanışlıdır
  • Ruby’de exception’lara, nil/false değerlerine ve nesne içi hata durumlarına dayanan yaklaşıma kıyasla Elixir’in açık ok/error dönüşlerinin daha tatmin edici olduğu; 3 aylık kullanımdan sonra bile yazma deneyiminin keyifli kaldığı düşünülüyor

Ruby deneyimi olan birinin Elixir’e uyum sağlama biçimi

  • Yeni iş yerinde backend’in ana dili olarak Elixir kullanılıyor; başlamadan önce Elixir veya Erlang kodu yazma deneyimi yoktu
  • Erlang, Prolog ile biraz uğraşmış olma deneyimi nedeniyle yabancı gelmedi; Elixir ise Ruby’den güçlü biçimde etkilenmiş söz dizimi sayesinde hızlı öğrenilebildi
  • Henüz en iyi uygulamalar, mimari ve daha düşük seviyeli Erlang kavramlarında uzman olunmasa da, bu noktalar Elixir’e girişin önünde engel olmadı
  • Elixir, Ruby’nin verdiği programlama keyfini korurken OOP dillerinde yaygın olan durumla ilgili tuzakları azaltan bir dil olarak benimsendi
    • Sınıf, instance ve kalıtım yoktur
    • Değişmezlik ve fonksiyonel stil üzerine kuruludur
    • Statik tip sistemine bağlı değildir
  • Değişebilir duruma sahip kodun bakımı çok daha zordur; durumun fonksiyon yerelinde mi, instance’ta mı yoksa sınıfta mı olduğu her zaman açık değildir
  • Ruby’de her şey nesne olduğu için her nesne durum taşıyabilir; sezgisel DSL’ler oluşturma sürecinde fonksiyon, instance ve sınıf seviyesindeki durumların karışması kolaydır
  • Ruby’nin Eigenclass kavramı, sınıfın sınıfı gibi düşünülebilir; bir instance’ın eigenclass’ı değiştirmesi diğer instance’ların durumunu da etkileyebilir

DSL ve derleme zamanı makroları arasındaki fark

  • Elixir de Ruby gibi DSL’leri destekler ve söz dizimi tanıdıktır; ancak temel fark DSL’in ne zaman oluşturulduğundadır
    • Elixir DSL’leri derleme zamanı makrolarıdır ve çalışma zamanı kodu üretir
    • Ruby DSL’leri çalışma zamanını değiştirerek nesneleri ve metotları dinamik olarak tanımlama yöntemine dayanır
  • Elixir makroları yanlış kullanılırsa kütüphanede hata oluşur; üretilen makro kodu yanlışsa derleyici hatası ortaya çıkar
    • Bu tür hatalar derleme zamanında göründüğü için testler gerçek uygulama mantığına daha fazla odaklanabilir

Pipeline ve with ile oluşan akış

  • Elixir’in pipeline operatörü |> kullanışlıdır, ancak Clojure’un threading operatörlerinin de avantajları vardır
    • Clojure’un -> operatörü, Elixir’in |> operatörü gibi önceki ifadenin sonucunu sonraki fonksiyonun ilk argümanı olarak geçirir
    • Clojure’un ->> operatörü, önceki sonucu sonraki fonksiyonun son argümanı olarak geçirir
    • Bu fark küçük görünse de anonim fonksiyon kullanmadan birlikte çalışabilir kod yazarken kullanışlıdır
  • Elixir’in with ifadesi, Haskell ve Lisp’teki let ifadesini çağrıştırırken yerleşik bir otherwise varmış gibi davranır
    • Karmaşık fonksiyonlar, üstte normal yol ve altta hata işleme olacak şekilde bölünebilir
    • {:ok, result} ile pattern matching yapılamazsa bu, kurtarılabilir hata olarak ele alınabilir; bu yüzden Result tuple’larıyla iyi uyum sağlar

Açık hata dönüşlerinin sağladığı avantaj

  • Ruby’de kontrol akışı için exception kullanımı yaygındır; açık hata tipleri yerine çoğu zaman başarılı sonuç, nil, false veya nesne içi hata durumuna dayanılır
    • Örneğin model.update(params) başarısız olduğunda false döndürür ve başarısızlık nedenini model.errors içinde saklar
    • Bu da yeniden değişebilir durum sorununa yol açar
  • Result / Either monad’larında olduğu gibi ok/error veya left/right değerlerini dönüş değeri olarak açıkça belirtme yaklaşımı, Ruby tarzı exception akışına göre daha tatmin edici hissettirir
  • Elixir’i 3 ay kullandıktan sonra bile Elixir, Ruby’nin gösterdiği “programlama eğlencelidir” hissini sürdüren bir dil olarak kalıyor

1 yorum

 
GN⁺ 2023-11-11
Hacker News yorumları
  • Son birkaç haftadır neredeyse her gün Elixir YouTube videoları izliyorum
    Kısa süre önce bir Elixir konferansı olmuş gibi; birkaçını izledikten sonra YouTube sürekli Elixir içerikleri önermeye başladı
    Erlang’ın fikirlerini seviyorum ama eskiden ejabberd sohbet sunucusu gibi şeylerle uğraşırken bana fazla tuhaf gelmişti
    Joe Armstrong videolarını her izlediğimde onun değeri bilinmemiş bir dâhi olduğunu düşünüyorum; izole süreçler ve mesaj iletimi, yani aktör modeli, dağıtık programlamanın geleceği için iyi bir aday gibi görünüyor
    Crockford’un yeni Misty dili videosunda https://www.youtube.com/watch?v=R2idkNdKqpQ da soruların Elixir/Erlang tarafına kaymış olması etkileyiciydi
    Yine de LiveView ve LiveBook’un “sihri”ne bakınca henüz %100 ikna olmuş değilim. Fazla iyi görünen şeylerde genelde bir tuzak çıkmıştır; GenServer gibi yabancı terimler ve platforma özgü bilgi de tek yönlü bir portaldan içeri giriyormuş hissi veriyor, başka yerlere taşınabilir bilgi olup olmadığından emin değilim
    Go’nun da oldukça iyi bir eşzamanlılık hikâyesi varken, küçük topluluğa sahip bir dil ve platform; işe alım, kütüphaneler ve kaynaklar açısından büyük risk taşıyor. Yine de Elixir topluluğunun başardıkları gerçekten etkileyici; tip sisteminin nasıl uygulanacağını da merakla bekliyorum

    • Eşzamanlılık tarafında biraz fazla endişeleniyorsun gibi. Sürecin ne olduğuna ve sendin nasıl çalıştığına bakmak yeterli
      GenServer, sayısız kez elle yazacağın bir örüntünün doğal biçimde genelleştirilmiş hâli; aktör bilgisi de başka yerlere taşınabilir
      Go’da da aktör soyutlamasını uygulayan kütüphaneler var; süreç posta kutusu da Go’nun kanalları gibi bir mesaj kuyruğu olarak görülebilir. Fark daha çok yorumlayıcının ve işlemciyi devretmenin nasıl çalıştığı tarafında
      Öte yandan LiveView’un sihir gibi görünmesi normal. Gerçekten de çok sayıda hareketli parça birbirine geçiyor ve birçok topluluğun son 10 yılda biriktirdiği çalışmaların sonucu; soyutlama çok olsa da fikrin kendisi olgun
      Riak gibi şeyler zamanının ilerisindeydi ve GenServer yapar gibi sağlam dağıtık sistemler kurabileceğin fikrine neredeyse sahipti
    • Elixir’i erken dönem topluluğunun dışına taşımak için gerçek bir ihtiyaç var ve bunun şu anda bir ölçüde gerçekleştiğini hissediyorum
      Hem Chris hem José, erken Elixir çevresinin dışında görünürlüğü artırmak için çok çaba harcıyor; topluluk içindeki insanlar da kendi seviyelerinde aynı şeyi yapıyor
      İşe alım sanıldığı kadar karmaşık değil. Bu dille çalışmak isteyen epey kişi var ve iyi geliştiriciler oldukça hızlı yetişiyor
      Yine de niş dil olma tarafını evcilleştirmek gerekiyor. Bu, dilin kendisi için bir risk ama kısa vadede niş bir teknolojide yetkin olmanın ödülünü de getirebiliyor
    • Ben tam tersini hissediyorum. Elixir öğrenildikten sonra daha az sihirli geliyor
      Çoğu şeyin ne yaptığını görüp anlayabiliyor ve kodu okuyabiliyorsun. JavaScript’te çoğu zaman durum böyle değil
      İşe almanın ve öğretici içerik bulmanın zor olduğu doğru. Örneğin Elixir’de yapmak istediğim şeyi daha önce yapmış birini bulmak JavaScript’e kıyasla çok daha zor
      Kütüphaneler büyük bir sorun olmadı; oldukça çok var. API’lerle çalışırken JavaScript veya Python için istemci kütüphaneleri olup Elixir için olmadığı durumlar oluyor; ama genelde yalnızca bir HTTP istemcisiyle API kullanmak çok da zor değil
    • Ruby’den Elixir’e, sonra tekrar Node.js’e geldim
      Şu anda Node.js kullanmam istememden değil, yapmak zorunda olmamdan. Denedikten sonra yeni bir projeye Node.js ile asla başlamayacağımı düşündüm
      Node.js’in eşzamanlılık kontrolü, ölçeklenebilirlik, güvenilirlik ve gözlemlenebilirlik araçları BEAM ekosisteminin çok gerisinde
      İnsanların Elixir’i inanması zor derecede iyi bulmasının nedeni, bazen dayanıklılık için tasarlanmamış platformlara fazlasıyla alışmış olmaları bence
    • LiveView ve LiveBook’un sihrinin ne olduğunu pek bilmiyorum
      LiveBook’ta fark hesaplama veya veri sıkıştırmanın tam ayrıntıları dışında doğru zihinsel modeli edinmek oldukça kolay. Sıkışırsan WebSocket mesajlarına bakarak da neler olduğunu epey anlayabiliyorsun
      LiveView şaşırtıcı derecede sezgisel
  • Elixir/Erlang’ın büyük cazibesi, web sunucusu bağlamında arka plan işlerini gerçekten kolay çalıştırabilmek ve bloklayan G/Ç’nin tüm sunucuyu durdurmasından endişe etmemek
    Önceki işimde bir webhook işleyicisinin içinde çok sayıda HTTP isteği yapmam gerekiyordu; aynı anda yeterince çok gerçekleştiğinde işletim sistemi süreçlerinin hepsi meşgul oluyor ve tüm site çöküyordu
    Böyle zamanlarda “Elixir olsaydı bir Task başlatıp devam ederdim” diye içten içe çok düşünmüştüm

    • Yakın zamanda yeni bir serviste Rust’tan Elixir’e geçtik; bunun oldukça büyük nedenlerinden biri de buydu
      Tokio async süreçleri arasında nesne paylaşma fikri, Elixir’in birinci sınıf özelliklerine kıyasla zor hissettirdi. İmkânsız ya da doğası gereği zor demiyorum ama doğru yapmak daha zor görünüyordu
    • Arka plan işlerinin bu şekilde kolaylaşmasını pek istemem
      Arka plan işlerini HTTP isteklerinden farklı bir hesaplama kapasitesi üzerinde tutmak isterim. Çünkü kaynak kullanım örüntüleri farklı; yeniden deneme, hata işleme ve backpressure’ı netleştirmek için öne bir durum veya kuyruk koymak isterim
      Elbette bu karmaşıklık olmasa ve aynı framework her şeyi halletse güzel olurdu; ama yalnızca programlama dili ya da runtime ile oraya kadar gidilebileceğini sanmıyorum. İzleme ve operasyon prosedürleri de çözümün parçası olmalı
  • Sasa Juric’in The Soul of Erlang and Elixir sunumu, bu dilin ne kadar güçlü olabileceğini iyi gösteriyor
    https://www.youtube.com/watch?v=JvBT4XBdoUE&t=4

    • Elixir’i merak ettiğim için bu haftanın başında bu sunumu izledim
      “Bırak çöksün” ya da “BEAM eşzamanlılığı doğru yapıyor” sözlerini duyup hâlâ kafasında oturtamayanlara şiddetle öneririm. Gerçekten harika bir sunum
  • 1991'den beri her gün Erlang ile programlama yapıyordum ve böyle devam etmeyi düşünüyordum.
    Bu süre içinde Haskell, Rust, Elixir gibi dilleri de denedim. Güçlü tipler çok değerli, ama sonunda mesele en çok nerede keyif aldığınıza geliyor.
    Erlang bana en büyük keyfi veren programlama dili ve birkaç yıl sonra emekli olana kadar en azından Erlang üzerinde hacklemeye devam etmeyi planlıyorum.

    • Hangi tür projeler üzerinde çalışmanın en eğlenceli olduğunu merak ediyorum.
  • Elixir'i tanıyalı bir yılı biraz geçti; öğrenmek ve çeşitli bileşenlere yerleştirip denemek oldukça keyifliydi.
    En büyük keyif, yalnızca BEAM/OTP ile yerleşik olarak gelen çok şey olmasından kaynaklanıyor.
    Birlikte çalıştığım ekipten biri bir keresinde “BEAM/OTP, karmaşık kısımları çıkarılmış k8s gibi” demişti.

    • Başka açıklamalar işe yaramadığında ekibe bunu böyle anlatıyorum.
      Birkaç yıl Elixir öğrendim, ama yakınlarda tasarladığım OpenShift, yani k8s geçişi yüzünden bu avantaj bir ölçüde seyreldi.
      k8s olmasaydı çok daha cazip bir öneri olurdu. Onun yerine mevcut geliştirme yığınını koruduk ve OTP ile yapacağımız şeyi k8s kavramlarıyla başardık. Elbette trade-off'lar farklıydı.
  • “Elixir, Ruby gibi eğlenceli bir dil verirken nesne yönelimli dillerin durumla ilgili mayınlarını ortadan kaldırıyor. Sınıf yok, instance yok, kalıtım yok; değişmez ve fonksiyonel, üstelik statik tip sistemine de bağlı değil.”
    Bunu istiyorum ama tipler de olsun isterdim. Büyük kod tabanlarında güçlü tiplerin doğru olduğuna eminim. Çünkü pek çok sihri görünür kılıyor ve akıl yürütmeyi kolaylaştırıyor.

    • Elixir'de bu sorun, Ruby veya Python gibi diğer dinamik dillere ya da değişkenliğe sahip statik dillere göre daha az.
      Fonksiyonların pattern matching/unification özelliği sayesinde verinin gidip gelirken hangi biçimde olduğunu epey iyi anlayabiliyorsunuz. Yine de içiniz rahat etmiyorsa Dialyzer var.
      Dialyzer, Erlang/Elixir için statik analiz aracıdır. Standart Erlang dağıtımına dahildir ve “DIscrepancy AnaLYZer for ERlang programs” ifadesinin kısaltmasıdır.
      Tek bir Erlang modülünde ya da uygulama paketlerinde tip hataları, ölü kod, gereksiz testler gibi tutarsızlıkları bulur. Doğru programları temel alarak tipleri çıkarır; tip anotasyonları zorunlu değildir, ama varsa daha iyi uyarılar sağlar.
      https://fly.io/phoenix-files/adding-dialyzer-without-the-pai...
    • Tipler geliyor. Umarım çok uzak değildir.
      https://elixir-lang.org/blog/2023/06/22/type-system-updates-...
    • Burada karşı taraftayım. Elixir'in GenServer'ında kalıtım olsaydı gerçekten iyi olurdu.
      GenServer nesneye yakındır; sadece ilişkili fonksiyonları olan bir struct değil, mesajlar üzerinden etkileşime girer.
      Projedeki GenServer'lar için ortak kayıt, bellek ayarları, logging gibi temel bir şablon koyup bunu üç farklı varyasyondaki belirli işlere göre özelleştirebilmek isterdim.
      Elixir bu sorunu makro kod üretimiyle kapatıyor ama pek iyi değil. Benim GenServer'larım önemsiz tekrarlarla dolu.
    • O zaman Gleam hoşunuza gidebilir. Benzer bir hissi var gibi görünüyor.
  • “Ruby'de kontrol akışı için exception kullanmak yaygındır” sözü bence düpedüz yanlış.
    O paragrafın ardından gelen örnek Rails'in update metodu, oysa standart Rails örneklerinde ve generator'larında kullanılan biçim exception kullanmayan update sürümüdür.

    • Örnekler, özellikle öğrenenler için karmaşıklığı sınırlayan basit bir yolu gösterir.
      Belirli bir ölçeğe ulaşmış kütüphane veya uygulamalar yeterince karmaşıklaştığında açıklayıcı hata sınıflarına geçer. Çünkü ActiveRecord'daki gibi durum tabanlı hata işleme acı vericidir.
      Ruby'de artık bir ölçüde pattern matching olduğuna göre, kontrol akışı için exception kullanımının yerini alabileceğini düşünüyorum. Exception fırlatmak yerine sınıfın kendisini döndürüp onunla eşleştirme yapabilirsiniz.
    • 2004'ten beri Ruby kullanan biri olarak bunun hiç de yanlış olduğunu düşünmüyorum.
      Pek çok gem kontrol akışı için exception kullanıyor; yazdığım veya bakımını yaptığım uygulama ve kütüphanelerde de bu yaygındı.
    • Ruby ve Rails aynı şey değil.
      Rails'te hata durumunda exception fırlatan çok sayıda bang! metodu var. Ancak genel olarak Ruby'de, Python'da olduğu gibi, kontrol akışı için exception kullanmak gerçekten yaygın.
  • F#’tan geldim ve Elixir’i sadece biraz kurcaladım; dil ne yazık ki biraz kafa karıştırıcı
    Örneğin fonksiyon imzası yalnızca adı ve parametre sayısını gösteriyor, tipleri göstermiyor; bu yüzden büyük kütüphanelerde neyin nereye girdiğini zihinde kavramak epey zor oluyor
    Yanlış parametre verdiğinizi de çoğu zaman ancak kodu çalıştırıp hata ayıkladıktan sonra görüyorsunuz. F# gibi katı tipli dillerde bu tür sorunlar kod yazarken hemen yakalandığı için zaman ve emek ciddi ölçüde azalıyor
    Bu yüzden Erlang ortamı dışında Elixir’in başlıca cazibesinin ne olduğunu merak ediyorum

    • Elixir’in statik tiplemesi aktif olarak geliştiriliyor
      https://elixir-lang.org/blog/2023/09/20/strong-arrows-gradua...
      Şu anda dinamik bir dil olduğu doğru; bu nedenle dilin kendisinden çok fazla tip bilgisi alamıyorsunuz. Henüz statik tipli bir dil değil
    • Elixir’in kendi içinde de sevilecek çok şey var. Makalede söylendiği gibi Ruby’den esinlenen sözdizimi hoş görünüyor ve öğrenmesi kolay
      Ancak kullandığım diğer dillere kıyasla Elixir’e üstünlük kazandıran şey gerçekten BEAM/OTP
      Deneyimime göre başka dillerde kütüphane olarak getirmeniz gereken birçok özellik varsayılan olarak geliyor. Bu tür kütüphaneler karmaşıklığı ciddi biçimde artırıyor ve bazen öğrenme eğrisi de yüksek oluyor. Asenkron ile ilgili özellikler buna iyi bir örnek
      Elixir’i bir süre kullanıp bu yerleşik araçları ve soyutlamaları öğrendiğinizde tüm ekosistemin gücünü anladığınızı düşünüyorum
    • Sadece dile bakarsak F#’a göre bir yükseltme demezdim. Öznel tabii
      Ana cazibesi muhtemelen Ruby hissi veren bir sözdizimiyle BEAM üzerinde çalışması. BEAM’in oldukça büyük bir avantaj olduğunu düşünüyorum
      F#’ın tipleriyle pek karşılaştırılamaz ama typespec kullanılabiliyor: https://hexdocs.pm/elixir/1.15.7/typespecs.html
    • .NET’i epey çok kullandım, F#’ı ise sadece ara sıra kullandım; Elixir’in birkaç cazibesi var
      Örneğin Axon, Nx, BumbleBee ile makine öğreniminin yerel olarak entegre olduğu ve GPU derlemesine kadar giden bir akış var: https://www.youtube.com/watch?v=HK38-HIK6NA
      Topluluk bu alanı gerçekten güçlü biçimde ileri taşıyor
      LiveView’in çalışma biçimi de çekici. Gerçi .NET’te Blazor var
      Elixir, gömülü sistemlerde Nerves veya betik yazımı gibi çeşitli bağlamlarda kullanılabiliyor. Bildiğim kadarıyla F# da betik yazımı için kullanılabiliyor
      Genel olarak BEAM ve ilgili yapılar güçlü yönleri; paket yöneticisi Hex de gerçekten iyi. Elbette .NET’in araçları da iyi
    • Fonksiyon parametrelerinde tip ipucu olmaması Elixir’de üretkenliğe en büyük darbeyi vuruyor
      typespec, pattern matching ve guard’larla idare edebilirsiniz ama epey zahmetli; en azından topluluk tarafından geliştirilen JetBrains eklentisinde IDE/IntelliSense dostu değil
  • Başlarken değil, 2 yıl kullandıktan sonra yazmak daha iyi olurdu
    Yeni şeyler başta her zaman kusursuz, parlak, her derde deva çözümler gibi görünür

    • Yazının yazarıyım ve balayı dönemi kavramına aşinayım
      İlk izlenimlerin de kendine göre bir yeri var; benim sunduğum da bu. Hedef kitle Elixir/Erlang uzmanları değil, Ruby uzmanları
    • Doktoraya başlamadan önce bundan daha uzun süre profesyonel olarak Elixir geliştiricisi olarak çalıştım
      Elixir o zaman da şimdi de bir mücevher gibi. Mükemmel değil ama şaşırtıcı derecede iyi dayanıyor
  • 2007 civarından beri Ruby kullanıyorum
    Bir sonraki “havalı” şeye geçmeye her çalıştığımda sonunda Ruby’ye döndüm; çünkü Ruby’yi seviyorum, Ruby ile en hızlı çalışabiliyorum ve mesele bundan ibaretti
    Ama son zamanlarda Elixir hakkında çok daha fazla şey görüyorum; dış görünüşü ve hissi hoşuma gidiyor. Yakında yeni bir yan proje başlatacağım, sanırım bir denemem gerekecek