Thursday, April 23, 2026

"Anlatıyor Olacağım": Türkçenin Gövdesine Saplanmış Bir Diken

Huzursuzluk

"Bu yazıda konuyu anlatıyor olacağım" cümlesini okuduğumda içimde bir huzursuzluk oluyor. Dilbilimsel bir refleks mi yoksa estetik bir tiksinme mi - tam olarak bilemiyorum. Ama bu yapının Türkçeye ne yaptığını biliyorum.

Meselenin Özü

Türkçe, zamanlama ve görünüş (aspect) kategorilerini çok zarif bir biçimde kodlayan bir dildir. Geniş zaman, gelecek zaman, süregelen eylem — bunların her biri ayrı ek sistemleriyle ifade edilir ve bu sistem yüzyıllardır tutarlı biçimde işlemektedir.

"Anlatacağım" bu sistemin ürünüdür. Gelecek zaman eki -acak/-ecek doğrudan eyleme bağlanır, kişi eki eklenir, cümle tamamdır. Yapı berraktır, ekonomiktir, işlevseldir.

"Anlatıyor olacağım" ise başka bir şeydir. Bu yapı, şu parçalardan oluşur:

  • anlat- (eylem kökü)
  • -ıyor (şimdiki zaman / süregelen görünüş eki)
  • ol- (yardımcı eylem)
  • -acak (gelecek zaman eki)
  • -ım (1. tekil kişi eki)

Ortada iki zaman eki var: -ıyor ve -acak. Bunları "süregelen gelecek" olarak yorumlamak mümkün mü? Teorik olarak evet — İngilizce future continuous yapısının (I will be explaining) bir kopyası gibi düşünülebilir. Ama Türkçenin bu ayrımı zaten başka araçlarla yaptığını, ve bu yapının büyük çoğunlukla o süregelen anlamı taşımadan kullanıldığını gözden kaçırmamak gerekir.

Anlambilimsel içeriği boş, sözdizimsel yükü ağır. Bu, kötü dil kullanımının tanımıdır.

Ne Zaman Ortaya Çıktı?

Bu yapının yükselişi yaklaşık 2010'ların ortasından itibaren hız kazandı. Başlangıcı belli: sunum dili, kurumsal konuşma, akademik jargon ve özellikle çeviri kaynaklı metinler. PowerPoint kültürünün Türkçeye hediyesidir büyük ölçüde.

Konuşmacı kürsüye çıkar ve şöyle der: "Bu sunumda size şirketin büyüme stratejisini aktarıyor olacağım, ardından rakip analizi yapıyor olacağız ve sonunda sorularınızı alıyor olacağız."

Tek bir cümlede üç kez. Kulağa ne kadar ciddi, ne kadar kurumsal, ne kadar profesyonel geliyor, değil mi?

Hayır. Kulağa şişirilmiş, boş, yılışık geliyor. Ama bunu söylemeye cesaret eden fazla kimse çıkmadı — çünkü bu dil bir statü işareti olarak benimsendi.

Toplumsal Dilbilim Boyutu

Burada dürüst olmak zorundayız: bu yapı dilbilgisel bir hata değildir. Türkçe bunu üretebilir. Mesele dilbilgisellik değil, tercihtir — ve bu tercihin arkasındaki toplumsal dinamikler ilginçtir.

Bu yapı bir prestij göstergesi işlevi görüyor. Kullananlar farkında olmadan şunu söylüyor: "Ben eğitimli biriyim, kurumsal ortamlarda bulunuyorum, İngilizce biliyorum, benim konuşmam sıradan değil."

Bu mekanizma yeni değil. Her dilde benzer süreçler yaşanmıştır — Latince kaynaklı kelimelerin İngilizce'de entelektüel prestij taşıması, Fransızcadan alınan sözcüklerin Osmanlı yazı dilinde statü göstergesi olması gibi. Ama fark şu: o örneklerde sözcük dağarcığı genişliyordu. Bu örnekte mevcut bir yapı gereksiz yere şişiriliyor.

Sonuç: dilin ekonomisi bozuluyor. Daha az anlamı daha çok sesle ifade etmek, dilbilimsel değer kaybıdır.

Peki Ya Gerçekten Fark Var mı?

"Yok mu hiç farkı?" diye sorabilirsiniz. Nadir durumlarda, evet.

Eğer biri şöyle diyorsa: "Siz burada oturuyorken, ben arka odada raporları inceliyor olacağım" — burada gerçek bir süregelen gelecek anlamı var. Eş zamanlılık söz konusu ve yapı o anlamı taşıyor.

Ama bu, istisnadır. Kuralı şöyle koyabiliriz: eğer "anlatacağım" yerinde kullanılabiliyorsa, "anlatıyor olacağım" demek dili şişirmektir. Kendinize dürüstçe sorun: gerçekten süregelen bir eş zamanlılık mı kastediyorum?

Sonuç

Türkçe, sesli-sessiz uyumu, eklemeli yapısı, özgür sözdizimi ve görünüş sistemiyle dünyanın biçimbilimsel açıdan en tutarlı dillerinden biridir. Gereksiz yapı şişirmesi bu tutarlılığa zarar verir.

"Anlatıyor olacağım" demek için özel bir neden yoksa, "anlatacağım" deyin.

Dil ekonomidir. Her kelime, her ek, her yapı bir şey ödemektedir — dikkat, zaman, anlam. Gereksiz ödeme yapmayın.


Bu yazıdaki görüşler dilbilimsel bir perspektiften kaleme alınmıştır. Kullanım normları toplumsal süreçlerle şekillenir; bu eleştiri dilin doğal evrimine karşı değil, bilinçsiz taklit ve statü kaygısıyla üretilen gereksiz karmaşıklığa karşıdır.

Thursday, April 9, 2026

DDC/CI ile monitör ayarlarının analog kontrolü bölüm 2.

Bir önceki yazıda Arduino Uno ve Python kullanarak DDC/CI protokolü üzerinden monitör parlaklık ve kontrast kontrolünü iki potansiyometreyle nasıl yapabileceğimizi anlatmıştım. O yazının sonunda birkaç yapılacak madde listelemiştim. Bu yazı o listedeki en kritik iki maddenin hayata geçirilmesini anlatıyor: Arduino'dan bağımsız bir MCU'ya geçiş ve uygulamanın Win32 ile yeniden yazılması.

Neden Arduino değil?

Arduino Uno güzel bir prototipleme platformu, ancak bu proje için fazla büyük ve gereksiz. Bizim ihtiyacımız olan tek şey iki ADC kanalı ve USB iletişimi. Bunun için 28 pinli bir AVR ve ayrı bir USB-Serial çevirici çipi kullanmak israf.

Daha da önemlisi, Arduino Uno USB üzerinden HID olarak görünmüyor — seri port (CDC) üzerinden haberleşiyor. Bu da Python tarafında pyserial kütüphanesi ve COM port yönetimi gerektiriyor. Farklı bilgisayarlarda farklı COM port numaraları atanıyor, kullanıcı bunu elle değiştirmek zorunda kalıyor.

Hedef: cihazı taktığında ek bir kurulum veya konfigürasyon gerektirmeden çalışan, native USB HID olarak görünen, mümkün olduğunca küçük bir devre.

CH552: USB HID yetenekli minimal MCU

WCH firmasının ürettiği CH552, bu iş için biçilmiş kaftan. Enhanced 8051 çekirdeği üzerine kurulu bu MCU'nun öne çıkan özellikleri:

  • Dahili USB full-speed transceiver — harici USB-Serial çeviriciye gerek yok
  • 4 kanallı 8-bit ADC (P1.1, P1.4, P1.5, P3.2)
  • 16KB program ROM, 1KB xRAM
  • DIP20 pakette mevcut — breadboard dostu
  • Adet fiyatı 0.5-1 dolar civarı
  • ch55xduino ile Arduino IDE desteği

Geliştirme için WeAct Studio'nun CH552 Core Board'unu kullandım. USB konektörü, boot ve reset butonu dahil, breadboard uyumlu, tüm pinler erişilebilir.


Bağlantı şeması

Devre son derece sade:

  • POT1 (Parlaklık): Orta bacak → P1.1, uçlar → GND / 3.3V
  • POT2 (Kontrast): Orta bacak → P1.4, uçlar → GND / 3.3V
  • Her iki pot için 10kΩ değer ideal
  • USB, hem güç hem veri için kullanılıyor

USB HID descriptor: Vendor HID

Önceki Arduino versiyonunda CDC (seri port) kullanıyorduk. Bu versiyonda cihaz native USB HID olarak görünüyor. Ancak burada önemli bir detay var: standart keyboard veya mouse descriptor kullanırsak Windows cihazı gerçek bir giriş aygıtı olarak tanımlıyor ve klavye girişlerini karıştırabiliyor.

Bunun yerine Vendor Defined HID (Usage Page 0xFF00) kullandım. Bu şekilde Windows cihazı tanıyor ama sistem giriş aygıtı olarak muamele etmiyor. Device Manager'da "HID-compliant device" olarak görünüyor, herhangi bir sürücü kurulumu gerekmiyor.

CH552 ADC: Dikkat edilmesi gereken detaylar

CH552'nin ADC'sini kullanırken birkaç önemli nokta var. Standart Arduino analogRead() fonksiyonu çalışıyor, ancak kanal seçimi biraz farklı. ch55xduino'da pin numaralandırması port.pin formatında: P1.1 için pin 11, P1.4 için pin 14.

Öte yandan ADC çıkışı 8-bit olmasına rağmen dahili referans voltajı nedeniyle değerler 0-255 aralığının tamamını kullanmıyor. Pratikte 4-174 arası bir aralık elde ettim. Python tarafında bu değerleri 0-100 aralığına map ediyorum:

ADC_MIN = 4
ADC_MAX = 174

def map_val(raw):
    val = (ADC_MAX - raw) * 100 // (ADC_MAX - ADC_MIN)
    return max(0, min(100, val))

Firmware: HID veri gönderimi

USB HID üzerinden veri göndermek için ch55xduino'nun HID keyboard örneğinin kaynak dosyalarını kullandım. Descriptor'ı Vendor HID olarak değiştirdim, veri gönderimi için mevcut USB_EP1_send() fonksiyonunu ve HIDKey[] buffer'ını kullandım.

Her HID paketi şu şekilde:

  • HIDKey[0] — Parlaklık (ADC P1.1)
  • HIDKey[1] — Kontrast (ADC P1.4)

Firmware ana döngüsü 50ms aralıklarla çalışıyor:

void loop() {
    uint8_t b = adc_read_ch(0);  // P1.1
    uint8_t c = adc_read_ch(1);  // P1.4

    HIDKey[0] = b;
    HIDKey[1] = c;
    USB_EP1_send();
    delay(50);
}

Cihazı flash'lamak için WCHISPTool kullandım. Boot moduna girmek için P3.6 butonuna basılı tutarken USB bağlamak yeterli.

Cold boot sonrası sorunu ve çözümü

Projeyi tamamladıktan sonra kritik bir bug fark ettim: devre Windows yeniden başlatıldıktan sonra resetlemeden çalışmıyordu. Sök-tak veya board reset sonrası her şey normal çalışıyordu, ancak bilgisayar kapatılmadan yeniden başlatıldığında potansiyometreler tepki vermiyordu.

Başlangıçta USB enumerate sorunu olduğunu düşündüm. Device Manager'da cihaz görünüyordu, hid.enumerate() ile descriptor bilgileri okunabiliyordu. Sorun farklı bir yerdeydi.

Kök neden UpPoint1_Busy flag'inin stuck kalmasıydı. Windows başlatma sırasında USB host controller enumerate sürecinde bir veya birden fazla USB bus reset sinyali gönderiyor. Eğer CH552 o anda EP1 üzerinden veri gönderiyorsa transfer yarıda kesiliyor; ancak USB_EP1_IN() callback'i tetiklenmediği için UpPoint1_Busy flag'i 1 olarak kalıyor. Bundan sonra USB_EP1_send() her çağrıda sessizce return 0 dönüyor — cihaz çalışır görünüyor ama hiç HID raporu göndermiyor. Kullanıcı CH552'yi fiziksel olarak resetleyince MCU yeniden başlar, flag sıfırlanır ve çalışır.

Çözüm USBhandler.c'deki UIF_BUS_RST interrupt handler'ına üç satır eklemekten ibaretti:

// USBhandler.c - UIF_BUS_RST handler
extern volatile __xdata uint8_t UpPoint1_Busy;

// ... handler içinde:
UsbConfig = 0;
UpPoint1_Busy = 0;  // Bus reset gelince stuck flag'i temizle

Bus reset geldiğinde UpPoint1_Busy sıfırlanıyor, bir sonraki USB_EP1_send() çağrısında transfer yeniden başlıyor. Windows'un başlatma sırasında gönderdiği bus reset sinyali artık sorunu çözmek için kullanılıyor. Soğuk açılışta artık resetlemeye gerek kalmadı.

Python daemon: Win32 ve dxva2

Önceki versiyonda Python GUI için tkinter, DDC/CI için monitorcontrol kütüphanesi kullanıyordum. Bu versiyonda her ikisini de değiştirdim.

OSD: tkinter yerine doğrudan Win32 GDI ile layered window. Transparan arka plan, her zaman üstte, tıklanamaz. Sağ alt köşede 2 saniye görünüp kayboluyor.

DDC/CI: monitorcontrol kütüphanesi yerine Windows'un native dxva2.dll API'si. SetMonitorBrightness ve SetMonitorContrast fonksiyonları doğrudan çağrılıyor. Bu yöntem hem daha hızlı hem de monitorcontrol kütüphanesinin yaşadığı "failed to get VCP feature" hatasını tamamen ortadan kaldırıyor.

dxva2 = ctypes.windll.dxva2

def _ddc_worker():
    while True:
        brightness, contrast = _ddc_queue.get()
        for h in _monitor_handles:
            if brightness is not None:
                dxva2.SetMonitorBrightness(h, brightness)
            if contrast is not None:
                time.sleep(0.05)
                dxva2.SetMonitorContrast(h, contrast)

DDC/CI komutları bir queue üzerinden tek bir worker thread'e gönderiliyor. Queue kapasitesi 1 — yeni komut geldiğinde işlenmemiş eski komut atılıyor. Bu sayede monitör hiçbir zaman komut yağmuruna tutulmuyor.

Sonuç

Arduino versiyonuyla karşılaştırıldığında bu versiyon birçok açıdan daha iyi:

  • COM port konfigürasyonu yok — USB tak çalıştır
  • Ayrı USB-Serial çevirici yok — tek çip, tek USB kablo
  • OSD daha responsive ve görsel olarak daha temiz
  • DDC/CI iletişimi daha stabil
  • Soğuk açılışta resetleme gerekmiyor
  • Devre boyutu ve maliyeti önemli ölçüde düştü

Yapılacaklar listesinde hala birkaç madde var: ADC gürültüsü için firmware tarafında smoothing buffer, Python daemon yerine standalone exe, ve nihai hedef olarak özel PCB tasarımı. Önümüzdeki yazılarda bunları ele alacağım.

Projenin kaynak kodlarına GitHub üzerinden ulaşabilirsiniz.

Wednesday, April 8, 2026

E=mc² ve Maddenin Gerçek Yüzü

Little Boy ve 0,7 Gram

1945'te Hiroşima'ya atılan Little Boy bombası yaklaşık 64 kg U-235 içeriyordu. Ama bunun sadece yaklaşık 1 kg'ı gerçekten fisyona girdi. Daha da çarpıcısı, bu reaksiyona giren kısmın da sadece yaklaşık 0,7 gramı saf enerjiye dönüştü.

Bunu sayıya dökersen:

\[ E = 0{,}0007 \times c^2 \approx 6 \times 10^{13} \text{ joule} \]

Bu da yaklaşık 15 kiloton TNT demek.

Yani koca 64 kg'lık sistemde:

  • %98'i reaksiyona bile girmiyor
  • Reaksiyona girenin de %99,9'u hâlâ "madde" olarak kalıyor

Ve yine de: bir şehir yok oluyor.

Bu tek başına şu cümleyi gerçek yapıyor: Madde inanılmaz yoğun bir enerji deposudur. Ama aynı zamanda şunu da gösteriyor: nükleer silahlar bile aslında çok verimsiz.

Kütle mi, Ağırlık mı?

Fiziği ilk öğrenirken dünya bize çok basit görünür. Cisimler vardır, ağırlıkları vardır, hareket ederler. Momentum da sanki "ağırlık çarpı hız" gibi bir şeydir. Ama işin içine girince ilk çatlak burada oluşur. Çünkü momentum aslında şöyle tanımlanır:

\[ p = mv \]

Burada \(m\) kütledir, ağırlık değil. Ağırlık ise tamamen farklı bir şeydir:

\[ W = mg \]

Biri cismin kendisiyle ilgili, diğeri bulunduğu ortamla. Dünya'da 80 kg olan biri Ay'da hâlâ 80 kg'dır ama ağırlığı ciddi şekilde düşer. Bu küçük ayrım aslında büyük bir kapıyı açar: ölçtüğümüz şey ile gerçek fiziksel büyüklük aynı şey olmayabilir.

Fiziğin Kalbi

Momentumun bu basit hali Newton dünyasında çalışır, ama biraz derine inince bunun sadece özel bir durum olduğunu fark ediyorsun. Daha genel çerçevede enerji ve momentum birlikte hareket eder:

\[ E^2 = (pc)^2 + (mc^2)^2 \]

Parçacık duruyorsa (\(p = 0\)), buradan direkt şu çıkar:

\[ E = mc^2 \]

Yani bir cismin sadece var olması bile enerji demektir. Ama daha da ilginci, kütle sıfırsa (\(m = 0\)) denklem şu hale gelir:

\[ E = pc \quad \Rightarrow \quad p = \frac{E}{c} \]

İşte ışığın sırrı burada. Kütlesi yoktur ama enerjisi vardır, dolayısıyla momentumu da vardır. "Momentumu taşıyan şey kütle değil, enerjidir" fikri ilk kez gerçekten anlam kazanır.

Einstein'ın Sıçraması

Bir cisim düşün, iki yana eşit ışık yayıyor. Kendi referansında hareket etmiyor, her şey dengede. Ama başka bir gözlemciye göre bu ışıkların enerjisi eşit değildir (Doppler etkisi). Momentum dengesi bozulur gibi görünür. Bu çelişkiyi çözmenin tek yolu şudur: cisim enerji kaybettiyse kütle de kaybetmelidir.

\[ \Delta m = \frac{E}{c^2} \]

Bu noktada "madde = enerji" artık slogan değil, zorunluluk haline gelir.

Parçacık Yok, Alan Var

"Madde enerjidir" dediğinde insan şunu sorar: peki bu somut şeyler nereden geliyor? Proton, nötron, elektron? Burada modern fizik sahneye çıkar ve der ki: evrende parçacık diye bir şey yoktur, aslında her şey alanların titreşimidir. Elektron bir elektron alanının, foton elektromanyetik alanın titreşimidir.

Proton ise daha karmaşık: quark ve gluon alanlarının birleşik bir enerji konfigürasyonu. Ve protonun kütlesinin büyük bölümü quarklardan gelmez. Asıl kaynak, onları bağlayan güçlü etkileşimin enerjisidir. Bu yüzden bir çekirdeğin toplam kütlesi, içindeki parçacıkların toplamından daha küçüktür. Aradaki fark:

\[ E_{\text{bağ}} = \Delta m \cdot c^2 \]

Fisyon ve füzyon tam olarak bu farktan enerji üretir. Little Boy'un "verimsizliği" de burada anlam kazanır: sistem çok daha büyük bir enerji rezervine sahipken onun sadece çok küçük bir kısmını kullanabilmiştir. Eğer teorik olarak 1 kg madde tamamen enerjiye dönüşseydi:

\[ E = 1 \times c^2 \approx 9 \times 10^{16} \text{ joule} \]

Bu, yaklaşık 21 megaton TNT ederdi. Hiroşima'daki patlamanın binlerce katı.

Işığı Tartabilir misin?

Bu noktada "katı madde" fikri tamamen çözülmeye başlar. Katılık, sadece atomlar arası elektromanyetik kuvvetlerin makroskopik etkisidir. Temel seviyede her şey enerji ve alan organizasyonudur. Bu yüzden ışık gibi tamamen kütlesiz bir şey bile mekanik etki yaratabilir — çünkü momentum taşıyordur.

Ama asıl zihin açan nokta şu: ışığı tek başına tartamazsın çünkü durduramazsın. Kütle dediğimiz şey aslında bir sistemin "durgun haldeki enerjisi" ile tanımlıdır. Foton için böyle bir durum yoktur, hep \(c\) ile gider. Ama ışığı bir kutunun içine hapsedersen, sistemin toplam momentumu sıfır olur ve artık bir "durgun sistem" elde edersin. O zaman sistemin kütlesi:

\[ m = \frac{E_{\text{toplam}}}{c^2} \]

kadar artar. Yani bir kutunun içine ışık koyarsan gerçekten daha ağır olur. Bir cismi ısıtırsan, içine enerji koyduğun için kütlesi artar. Fark çok küçüktür ama prensip kesindir.

Yerçekimi ve Eğri Uzay

Son adımda yerçekimine baktığında yine aynı hikâyeyi görürsün. Newton'a göre yerçekimi bir kuvvettir ve kütleleri çeker. Ama Einstein'a göre kütle ve enerji uzay-zamanı büker. Işık da bu eğri geometri içinde hareket eder. Bu yüzden bükülür — "çekildiği" için değil, bulunduğu uzay eğri olduğu için yolunu değiştirir.


Bütün bu hikâyeyi tek bir cümleyle özetlemek mümkün: evren, katı nesnelerden oluşan bir yer değil; enerji ve alanların belirli kurallara göre organize olmuş halidir. Kütle, momentum, bağ enerjisi ve yerçekimi, bu organizasyonun farklı yüzleridir.

Ve en güzel tarafı şu: bu hikâyeyi gerçekten anlamaya başladığın anlar hep aynı şekilde geliyor — "oha" 😄

Sunday, April 5, 2026

Steelseries Engine 3 ve Rival 100 not connected problemi.

Rival 100 mouse kullanıyorum. Bazen soldaki B4-B5 tuşlarına atadığım ses kontrolü çalışmıyor.

SteelSeries Engine 3'ü açıp bakınca Rival 100'ün yanında Not Connected yazıyor.

Mouse takılı ve çalışıyor, ama Steelseries Engine 3 yazılımı mouse'u görmüyor.

SteelSeries Engine 3, mouse'u tanıyamazsa tüm özel atamalar devre dışı kalıyor. Volume up, volume down, ben sadece bu tuşları kullandığım bunlar gidiyor, muhtemelen diğer atamalar da gidiyordur, denemedim. Çözüm için USB'yi çıkarıp takıyorum ya da bilgisayarı yeniden başlatıyorum, sorun geçici olarak düzeliyor. Ama bu her seferinde yapılacak bir şey değil. Zaten sonra rastgele bir restartta tekrar ediyor.

Rival 100, Windows'a USB Composite Device olarak bağlanıyor. Yani tek bir fiziksel cihaz, Windows'a birden fazla giriş olarak görünüyor. Bunların hepsinin düzgün başlatılması gerekiyor.

Bazen sistem açılışında bu başlatma süreci aksıyor. Mouse fiziksel olarak çalışıyor ama Engine 3 cihazı recognize edememiş oluyor.

Device Manager'da driver uninstall/reinstall yapmak işe yaramıyor.

Yazılımsal çözüm: USBDeview

Fiziksel olarak USB'yi çıkarıp takmanın tam yazılım karşılığı NirSoft'un ücretsiz aracı USBDeview.

İndirme linki: nirsoft.net/utils/usb_devices_view.html

Kurulum yok, portable .exe.

  1. USBDeview yönetici olarak çalıştırılır. (Sağ tık → Run as Administrator)
  2. Listede SteelSeries Rival 100 için üç satır var: USB Composite Device olanı resetlenecek.
  3. Üzerine sağ tıklayıp, Disable+Enable seçilir.
  4. Engine 3 kapatıp açılır.

Mouse connected görünüyor, atamalar geri geliyor.

Neden Composite Device? Çünkü diğer iki girişin (HID ve USB Input Device) ebeveyni o. Onu sıfırlayınca altındaki her şey yeniden başlatılıyor. Tek tek uğraşmaya gerek yok.

Kalıcı çözüm: USB güç tasarrufunu kapatmak

USBDeview sorunu çözüyor. Ama sorun tekrar yaşanıyor. 

Sebep büyük ihtimalle Windows'un USB güç tasarrufu özelliği. Bu seçenek belirli koşullarda USB cihazlarını uyutabiliyor. Mouse fiziksel olarak çalışmaya devam ediyor ama Engine 3 bağlantıyı kaybediyor.

Kapatmak için:

  1. Denetim Masası → Güç Seçenekleri
  2. Aktif planın yanındaki Plan ayarlarını değiştir
  3. Gelişmiş güç ayarlarını değiştir
  4. USB ayarları → USB seçici askıya alma ayarı → Devre dışı

Şimdilik bu kadar. Sorunun tekrarlanıp tekrarlamadığını birkaç gün izleyeceğim.


Friday, April 3, 2026

Açık Kaynağın Karanlık Yüzü: Dependency Hell ve Güvenlik Kabusu

"Sadece npm install yap"


Bir uygulama geliştirmeye karar verdiniz. Modern, açık kaynak araçlar kullanacaksınız. Ücretsiz, özgür, topluluk destekli. Harika.

İlk komutunuzu yazıyorsunuz:

npm install

Ve başlıyor. Ekran dolup taşıyor. Yüzlerce paket, onlarca uyarı, birkaç hata. Beş dakika sonra hâlâ kurulum yapıyor. On dakika sonra bir şeyler ters gidiyor.

Hoş geldiniz. Dependency hell'e düştünüz.

Bu nasıl bir yer?

Bir Node.js projesi açın, node_modules klasörüne bakın. Siz 5 paket istediniz. Ama orada 1.500, belki 2.000 paket vardır. Geri kalanı ne?

Onların bağımlılıkları. Onların bağımlılıklarının bağımlılıkları. Onların bağımlılıklarının bağımlılıklarının bağımlılıkları.

Bir paket "A" ister, A paketi "B v2.x" ister, başka bir paket "B v3.x" ister, ikisi uyuşmaz, Metro bundler çöker, ekran kırmızıya döner. Günün geri kalanı bu hatayla geçer.

npm ekosisteminde 2 milyondan fazla paket var. Bu sayı her gün büyüyor. Hiçbir merkezi denetim mekanizması yok. Herkes her şeyi yayınlayabiliyor.

left-pad: İnternetin 11 Satıra Bağlı Olduğu Gün

2016 yılında Azer Koçulu isminde bir geliştirici, npm'deki "left-pad" adlı paketini sildi. Bir hukuki anlaşmazlık yüzünden kızmıştı, paketi çekti.

left-pad ne yapıyordu? Bir string'in soluna boşluk ekliyordu. 11 satır kod.

Sonuç: React çöktü. Babel çöktü. Binlerce proje build edilemez hale geldi. Dünyanın dört bir yanında CI/CD pipeline'ları durdu. Şirketler saatler içinde milyonlarca dolar kaybetti.

İnternetin önemli bir kısmı, tek bir insanın sinirli bir öğleden sonrasına bağlıydı.

event-stream: Hacker'ın Hediyelik Paketi

2018'de daha da ürkütücü bir şey yaşandı.

"event-stream" popüler bir npm paketiydi. Geliştirici paketi artık aktif olarak sürdürmediğini, devretmek istediğini açıkladı. "right9ctrl" isimli biri gönüllü oldu ve paketi devraldı.

Haftalarca kimse fark etmedi. Ta ki bir araştırmacı, paketin içine gizlenmiş kod parçasını bulana kadar.

O kod ne yapıyordu? Kullanıcıların kripto para cüzdanlarını arıyor, özel anahtarları çalıyordu. Hedef spesifikti: Copay isimli bir Bitcoin cüzdan uygulaması.

Paket bu sürede milyonlarca kez indirilmişti.

Peki kim fark etti? Bir GitHub kullanıcısı. Gönüllü, ücretsiz çalışan biri.

Kim Denetliyor?

Kısa cevap: Kimse.

npm'in otomatik tarama sistemleri var. Bilinen zararlı yazılım imzalarını arıyor. Ama sıfırıncı gün saldırıları için, özellikle hazırlanmış hedefli kötü kod için bu taramalar kör.

Büyük şirketler kendi çözümlerini üretmiş durumda. Google, Meta, Microsoft kritik paketleri fork edip kendi güvenlik ekiplerinden geçiriyor. Ama bu lüks her şirkete nasip olmuyor.

Snyk, Dependabot, Socket gibi araçlar bilinen açıkları takip ediyor. CVE veritabanlarıyla karşılaştırıyor. Faydalılar, ama reaktifler: açık önce bulunuyor, sonra işaretleniyor, sonra siz güncelliyorsunuz. Bu arada ne kadar süre geçiyor?

Açık Kaynak'ın Trajedisi

Burada bir paradoks var.

Açık kaynak, yazılım dünyasını demokratikleştirdi. Bir öğrenci, dünyaca kullanılan bir kütüphane yazabiliyor. Küçük şirketler, enterprise araçları ücretsiz kullanabiliyor. Bilgi paylaşılıyor, ilerleme hızlanıyor.

Ama bu ekosistem, gönüllü emeği üzerine kurulu. Ve gönüllü emek tükeniyor.

"left-pad" geliştiricisi yoruldu, bıraktı. "event-stream" geliştiricisi yoruldu, devretti. Her gün onlarca kritik paket, hayatının farklı bir dönemine geçmiş, artık ilgilenemeyen biri tarafından "sürdürülüyor."

Siz o paketi kullanıyorsunuz. Onun bağımlılığının bağımlılığı olarak. Habersizce.

Microsoft'un Kapalı Dünyası Daha mı İyiydi?

Nostalji tehlikeli. Eski Microsoft dünyasının da bedelleri vardı.

Her şey Windows'a kilitliydi. Lisanslar pahalıydı. Topluluk katkısı neredeyse sıfırdı. "Linux bir kanser" diyen bir şirketten bahsediyoruz. Yenilik yavaştı, her şey Microsoft'un roadmap'ine bağlıydı.

O dünya güvenliydi çünkü dardı. Bugünkü dünya özgür ama kaotik.

İkisi arasında sağlıklı bir denge henüz bulunamadı.

Ne Yapmalı?

Bağımlılıklarınızı tanıyın. npm ls ile dependency tree'ye bakın. Her paketin ne yaptığını en azından kabaca bilin.

Sürümleri kilitleyin. package-lock.json'u commit edin. ^ ve ~ versiyonlarına dikkat edin, her npm install'da farklı bir şey kurulabilir.

Güvenlik taraması yapın. npm audit çalıştırın. Snyk veya Dependabot entegre edin. Mükemmel değil ama hiç yoktan iyi.

Az bağımlılık, daha az risk. Her şey için paket kurmak yerine zaman zaman kendiniz yazın. 11 satırlık bir şey için left-pad kurmayın.

Büyük, aktif topluluğa sahip paketleri tercih edin. Son commit tarihi 4 yıl önceyse, o paket için iki kez düşünün.

Son Söz

Bugün bir uygulama kurarken Node versiyonu uyumsuzluğu, Expo SDK çakışması, TurboModule hatası, babel-preset eksikliği derken saatler harcadım.

Şikâyet etmek kolay. Ama şunu da söylemek lazım: bu kaotik, güvensiz, yorucu ekosistemi gönüllüler inşa etti. Ücretsiz. Bazen gecenin üçünde. Karşılıksız.

Belki de asıl sorun, milyar dolarlık şirketlerin bu gönüllü emeğin üzerine ticari ürünler inşa etmesi ve o emekçilere yeterince geri vermemesi.

Ama bu başka bir yazının konusu.


Bu yazıyı bir React Native uygulaması kurulum hatasının 15. dakikasında yazmaya karar verdim. Uygulama 1.5 saatte çalıştı.