Soldan Sağa Programlama
(graic.net)- Soldan sağa programlama yaklaşımında, kod yazılır yazılmaz program geçerli durumda kalır; bu da editörün otomatik tamamlama gibi araç desteğini en üst düzeye çıkarır
- Python’un liste üreteçleri, bildirilmeyen değişkenler ve tip çıkarımının yokluğu nedeniyle otomatik tamamlama işlevini engeller
- Rust ve JavaScript, programın soldan sağa doğal biçimde kurulmasına izin verdiği için değişken kullanımı ve metot keşfi daha sezgiseldir
- C ve Python’daki fonksiyonel stil, fonksiyon adı ya da yapının kolay keşfedilememesi nedeniyle verimli bir kodlama deneyimini zayıflatır
- Karmaşıklığı yüksek mantıkta, soldan sağa açılan kod daha kolay okunur; bakım ve genişletilebilirlik açısından daha üstündür
Soldan Sağa Programlama
Kod, yazıldığı anda geçerli olmalı
Python liste üreteçlerinin sınırları
- Python liste üreteci sözdizimi
words_on_lines = [line.split() for line in text.splitlines()], bildirilmeyen bir değişkene (line) erişmeyi gerektirdiği için editörün otomatik tamamlama ya da tip çıkarımı desteğini düzgün sağlayamaması sorununu doğurur - Kodu parça parça yazma sürecinde
words_on_lines = [line.spgibi yazıldığında editörlinedeğişkeninin tipini bilemediğinden metot öneremez- Değişken adı yazım hataları (
limegibi) gibi potansiyel hataları tespit etmek de zorlaşır
- Doğru önerileri alabilmek için tamamlanmamış kod yazmak gerekir; bu süreç sezgisel değildir ve rahatsız edicidir
Rust’ta soldan sağa kurulum
- Rust örneği (
let words_on_lines = text.lines().map(|line| line.split_whitespace());) şunu gösterir:- Anonim fonksiyon bildirilirken değişken (
line) ilk göründüğü anda bildirilmiş sayılır; böylece hemen otomatik tamamlama ve metot önerileri kullanılabilir - Nitekim
split_whitespacemetodu da otomatik öneri sayesinde kolayca bulunabilmiştir
- Anonim fonksiyon bildirilirken değişken (
- Bu yaklaşımda program her zaman kısmen de olsa geçerli durumda kaldığı için IDE ya da editör kod yazımını gerçek zamanlı destekleyebilir
Aşamalı Açığa Çıkarma (Progressive Disclosure) ve API kullanılabilirliği
- Aşamalı Açığa Çıkarma (Progressive Disclosure), kullanıcının yalnızca ihtiyaç duyduğu kadar karmaşıklıkla karşılaşmasını sağlayan bir tasarım ilkesidir; programlamaya da uygulanabilir
- Örnek: Bir kelime işlemcide yalnızca görsel eklendiğinde ilgili seçeneklerin görünmesiyle benzerlik taşır
- C dili bu tür desteği yeterince sunmaz
FILE *fileile ilişkili tüm fonksiyonlarfile.üzerinden keşfedilemediği içinfread,fclosegibi fonksiyon adı kalıplarını ezberlemek gerekir ve işlevleri keşfetmek zordur- Buna karşılık ideal bir dilde
file.üzerinden metot önerileriyle ilgili işlevler kolayca aşamalı olarak keşfedilebilir
Fonksiyon ve metot keşfedilebilirliği arasındaki fark
- Python’daki
map(len, text.split())ile JavaScript’tekitext.split(" ").map(word => word.length)örneklerinin karşılaştırılması- Python’da
len,length,sizegibi isimler öngörülemediğinden doğru işlevi bulmak için birkaç deneme yapmak gerekebilir - JavaScript’te
word.sonrasına yalnızca.lyazmak bile editörünlengthgibi metotları önermesini sağlar; bu da keşfedilebilirliği artırır mapgibi yüksek mertebeden fonksiyonlarda bile gerçek dönüş değeri ve veri tipi anında daha açık hale gelir
- Python’da
Mantık karmaşıklaştıkça yapısal yazımın avantajı
- Karmaşıklığı yüksek mantıkta (
filter,lambdaiç içe geçmiş uzun Python kodu gibi)- Kodun başını ve sonunu tekrar tekrar kontrol etmek gerekir; koşul ifadeleri ya da parantez eşleştirmeleri nedeniyle okunabilirlik düşer ve anlamak zorlaşır
- Aynı mantığın JavaScript sürümünde ise kod yukarıdan aşağıya, soldan sağa sıralı biçimde okunup anlaşılabilir
Temel ilke
Kod, girildiği her anda geçerli olmalı
- Tek başına
textyazmak bile programın geçerli durumda kalmasını sağlar text.split(" ")yazıldığında da, ardından.map(word => word.length)eklenirken de, bütün olarak ara durumlar her zaman geçerlidir- Bu tür bir kodlama deseni, editörün gerçek zamanlı destek sunabilmesini artırır; REPL ortamında ise sonuçlar anında görülebilir
Sonuç
- API ve dil tasarımı, kodun soldan sağa doğal biçimde yazılmasını ve her ara adımda geçerli bir program oluşturulmasını desteklemelidir
- İyi API tasarımı, bu kod yazma deneyimini iyileştirmenin temel unsurudur
1 yorum
Hacker News görüşleri
FROMyerineSELECTile başlaması; bu yüzden hangi varlıkla (tabloyla) çalıştığını hemen anlamak zor oluyor ve akıllı editörlerin sorgu yazımını daha verimli desteklemesini de engelliyor.FROM -> SELECT -> WHEREsırası daha doğal geliyor; özellikle deSELECTbölümünde sütun adları belirlenipWHEREiçinde bunlara başvurulduğu için. HattaSELECT * FROM tableyerine yalnızcaFROM tableyazıldığındaSELECTbölümünün atlanabilmesi gerektiğini düşünüyorum. Bu şikayetler yüzünden dırdırcı bir ihtiyar gibi görünebilirim ama bu sadece kişisel bir özlemim.FROM'un önce geldiği sorgu sırasını kullanıyor. BigQuery'ye de yakın zamanda pipe/ok sözdizimi eklendi, DuckDB için de topluluk eklentileri var; tavsiye ederim: DuckDB - PSQL, DuckDB - PRQLWHEREiçinde sütun takma adı kullanılamaz; çünkü selection (WHERE), projection'dan (SELECT) önce gerçekleşir. Ayrıca MySQL 8'deTABLE <table>diye bir sözdizimi de var, buna da bakılabilir.FROM -> WHERE -> SELECTşeklindedir. Bu yüzdenSELECTiçinde tanımlanan sütun takma adlarıGROUP BY,HAVING,ORDER BYiçinde kullanılabilirkenWHEREiçinde kullanılamaz.FROMile başlayan bir yapı kullanıyor. Ayrıca IDE'de diğer bölümleri yazarken otomatik tamamlama sayesinde alan önerilerini hemen almak mümkün olduğu için bu yapıyı iyi buluyorum.FROMile başlayan varyantların daha aktif biçimde eklenmesi gerektiğini düşünüyorum ve bunun da zor bir iş olduğunu sanmıyorum. Kullanılabilirliği artırmaya dönük denemeler yetersiz kalıyor.fordöngüsüyle aynı şeydir. Herkes Python'un tür sisteminin gevşekliğinden şikayet ederken, dönüş türünü açıkça belirleyen tek sözdiziminin (liste comprehension) hedef alınması garip. Rust dahil çoğu başka dilde de sırafrom iter as varşeklinde değil. Dillerin fonksiyon çağırma sözdizimlerini karşılaştırmak da ilginç olabilir (functools.mapPython'da da var sonuçta).returnvb.).Tabile yer tutucuları tek tek doldurma özelliği var. Bu durumdaTabile ilerleme sırasının mutlaka soldan sağa olması gerekmez; örneğin{3} for {2} in {1}gibi bir sıra da mümkün. Bu tür araçlar, "okuması kolay sözdizimi" ile "yazması kolay sözdizimi" arasında bir uzlaşma sunuyor. Ben, araçlardan yararlanmak gerekse bile okunabilir sözdizimini önceleyen taraftayım. Mutlakafor-inyapısına saplanmak gerekmiyor.'let foo = ...'gibi sonucu değişkene atamak yerine'... =: foo'gibi bir biçimi denemek ilginç olurdu.bake(divide(add(knead(mix(flour, water, sugar, butter)),eggs),12),450,12)gibi iç içe yazmak yerine,mix(flour, water, sugar, butter) %>% knead() %>% add(eggs) %>% divide(12) %>% bake(temp=450, minutes=12)şeklinde pipe ile yazmak çok daha kolay ve anlaşılır.from some_library import child_modulesözdizimi oldukça sezgisel. JS'de iseimport { asYetUnknownModule } from SomeLibraryyapısı bana çok daha az sezgisel geliyor.fromanahtar sözcüğüne bu kadar takıldığınızı anlamıyorum. Basitçe gibi bir şey de olabilirdi.len(list(filter(lambda line: all([abs(x) >= 1 and abs(x) <= 3 for x in line]) and (all([x > 0 for x in line]) or all([x < 0 for x in line])), diffs)))gibi yazmak yerine NumPy array kullanmak, bellekte yeni bir liste oluşturmaya gerek bırakmaz ve tüm satırı bir seferde ele almak açısından çok daha iyidir. Örneğin bence "soldan sağa" fikrini çok daha iyi yansıtıyor.