<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://sonsuzus.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://sonsuzus.github.io/" rel="alternate" type="text/html" /><updated>2026-07-13T10:43:55+00:00</updated><id>https://sonsuzus.github.io/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">C++ ile Yapay Sinir Ağları Temelleri: Vektörleri Hızlandır, Modeli Uyandır</title><link href="https://sonsuzus.github.io/posts/c-ile-yapay-sinir-aglari-temelleri-vektorleri-hizlandir-modeli-uyandir/" rel="alternate" type="text/html" title="C++ ile Yapay Sinir Ağları Temelleri: Vektörleri Hızlandır, Modeli Uyandır" /><published>2026-07-13T00:00:00+00:00</published><updated>2026-07-13T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/c-ile-yapay-sinir-aglari-temelleri-vektorleri-hizlandir-modeli-uyandir</id><content type="html" xml:base="https://sonsuzus.github.io/posts/c-ile-yapay-sinir-aglari-temelleri-vektorleri-hizlandir-modeli-uyandir/"><![CDATA[<p>Yapay sinir ağları kulağa çoğu zaman Python kütüphanelerinin sihirli düğmeleri gibi gelir; fakat sahnenin arkasında olan şey oldukça “mekanik”tir: vektörler çarpılır, matrisler toplanır, türevler hesaplanır ve bellekten veri taşınır. C++ burada devreye girer; çünkü düşük seviyeli bellek kontrolü sayesinde yalnızca modeli değil, modelin öğrenirken yürüdüğü matematiksel yolu da optimize edebiliriz.
``
Bir yapay sinir ağını en sade haliyle düşünelim: Girdi vektörü $x$, ağırlık matrisi $W$, bias vektörü $b$ ve aktivasyon fonksiyonu $f$. Tek katmanlı bir ileri yayılım şu şekilde yazılır: $y = f(Wx + b)$. Burada “öğrenme” dediğimiz şey, $W$ ve $b$ değerlerini kayıp fonksiyonunu azaltacak şekilde güncellemektir. Örneğin ortalama kare hata için $L = \frac{1}{n}\sum (\hat{y}-y)^2$ kullanabiliriz.</p>

<p>C++ ile çalışırken kritik soru şudur: Bu matematiksel ifadeleri bellekte nasıl temsil edeceğiz? Çünkü CPU, veriye hızlı erişirse hesaplama da hızlanır. Dağınık <code class="language-plaintext highlighter-rouge">std::vector&lt;std::vector&lt;float&gt;&gt;</code> yapıları okunabilir olsa da satırlar bellekte parçalı durabilir. Tek boyutlu, ardışık bir dizi ise cache dostudur.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Bellek Düzeni</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">vector&lt;vector&lt;float&gt;&gt;</code></td>
      <td>Parçalı</td>
      <td>Kolay anlaşılır</td>
      <td>Cache kaçırma olasılığı yüksek</td>
    </tr>
    <tr>
      <td>Tek boyutlu <code class="language-plaintext highlighter-rouge">vector&lt;float&gt;</code></td>
      <td>Ardışık</td>
      <td>Hızlı erişim, SIMD’ye uygun</td>
      <td>İndeks hesabı gerekir</td>
    </tr>
    <tr>
      <td>Ham pointer / aligned buffer</td>
      <td>Kontrollü</td>
      <td>En yüksek optimizasyon alanı</td>
      <td>Hata yapması kolay</td>
    </tr>
  </tbody>
</table>

<p>Bir matrisi tek boyutlu sakladığımızda $W_{ij}$ elemanına erişim formülü şöyledir: $index = i \times cols + j$. Bu küçük formül, C++ tarafında büyük performans farkları yaratabilir.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;cmath&gt;</span><span class="cp">
</span>
<span class="k">struct</span> <span class="nc">DenseLayer</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">in</span><span class="p">,</span> <span class="n">out</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">float</span><span class="o">&gt;</span> <span class="n">W</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">float</span><span class="o">&gt;</span> <span class="n">b</span><span class="p">;</span>

    <span class="n">DenseLayer</span><span class="p">(</span><span class="kt">int</span> <span class="n">input</span><span class="p">,</span> <span class="kt">int</span> <span class="n">output</span><span class="p">)</span>
        <span class="o">:</span> <span class="n">in</span><span class="p">(</span><span class="n">input</span><span class="p">),</span> <span class="n">out</span><span class="p">(</span><span class="n">output</span><span class="p">),</span> <span class="n">W</span><span class="p">(</span><span class="n">input</span> <span class="o">*</span> <span class="n">output</span><span class="p">),</span> <span class="n">b</span><span class="p">(</span><span class="n">output</span><span class="p">)</span> <span class="p">{}</span>

    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">float</span><span class="o">&gt;</span> <span class="n">forward</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">float</span><span class="o">&gt;&amp;</span> <span class="n">x</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">float</span><span class="o">&gt;</span> <span class="n">y</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="mf">0.0f</span><span class="p">);</span>

        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">out</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
            <span class="kt">float</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">b</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
            <span class="k">const</span> <span class="kt">int</span> <span class="n">row</span> <span class="o">=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">in</span><span class="p">;</span>
            <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">in</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">sum</span> <span class="o">+=</span> <span class="n">W</span><span class="p">[</span><span class="n">row</span> <span class="o">+</span> <span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">x</span><span class="p">[</span><span class="n">j</span><span class="p">];</span>
            <span class="p">}</span>
            <span class="n">y</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">tanh</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="c1">// aktivasyon</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">y</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Bu kodda <code class="language-plaintext highlighter-rouge">W</code> matrisi tek boyutlu tutulur. <code class="language-plaintext highlighter-rouge">row + j</code> erişimi, satırdaki elemanları ardışık okuduğu için işlemci önbelleğiyle iyi anlaşır. Yani CPU’ya “al bakalım, sıradaki veriler tam yanında” demiş oluruz. Bu da özellikle büyük katmanlarda önemlidir.</p>

<p>Öğrenme aşamasında geri yayılım devreye girer. Temel fikir zincir kuralıdır: $\frac{\partial L}{\partial W} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial W}$. Ardından ağırlıklar şu şekilde güncellenir: $W := W - \eta \frac{\partial L}{\partial W}$. Buradaki $\eta$ öğrenme oranıdır; çok büyükse model zıplar, çok küçükse kaplumbağa gibi ilerler.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Matematiksel Rol</th>
      <th>C++ Optimizasyon Noktası</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ağırlık matrisi</td>
      <td>Öğrenilen dönüşüm</td>
      <td>Ardışık bellek, hizalama</td>
    </tr>
    <tr>
      <td>Aktivasyon</td>
      <td>Doğrusal olmayanlık</td>
      <td>Hızlı fonksiyon seçimi</td>
    </tr>
    <tr>
      <td>Gradyan</td>
      <td>Güncelleme yönü</td>
      <td>Geçici kopyaları azaltma</td>
    </tr>
    <tr>
      <td>Batch</td>
      <td>Paralel veri işleme</td>
      <td>Döngü düzeni, SIMD, thread</td>
    </tr>
  </tbody>
</table>

<p>Performans için dikkat edilmesi gerekenlerden biri gereksiz kopyalardır. Büyük vektörleri fonksiyonlara değer ile geçirmek yerine <code class="language-plaintext highlighter-rouge">const reference</code> kullanmak gerekir. Ayrıca eğitim döngüsünde sürekli yeni bellek ayırmak pahalıdır; mümkünse buffer’lar önceden oluşturulmalı ve tekrar kullanılmalıdır.</p>

<p>Daha ileri seviyede <code class="language-plaintext highlighter-rouge">alignas(64)</code>, SIMD komutları, OpenMP veya BLAS kütüphaneleri kullanılabilir. Ancak temeli anlamadan bu araçlara atlamak, turbo motoru bisiklete takmaya benzer. Önce veri yerleşimi, döngü sırası ve matematiksel akış net olmalıdır.</p>

<p>C++ ile sinir ağı yazmak, hazır kütüphane kullanmaya göre daha zahmetlidir; fakat karşılığında modelin kalp atışını duyarsınız. Her çarpım, her toplama, her bellek erişimi sizin kontrolünüzdedir. İşte bu yüzden C++, yapay sinir ağlarını yalnızca kullanmak değil, gerçekten anlamak isteyenler için harika bir laboratuvardır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="C++" /><category term="Yapay Sinir Ağları" /><category term="Optimizasyon" /><summary type="html"><![CDATA[Yapay sinir ağları kulağa çoğu zaman Python kütüphanelerinin sihirli düğmeleri gibi gelir; fakat sahnenin arkasında olan şey oldukça “mekanik”tir: vektörler çarpılır, matrisler toplanır, türevler hesaplanır ve bellekten veri taşınır. C++ burada devreye girer; çünkü düşük seviyeli bellek kontrolü sayesinde yalnızca modeli değil, modelin öğrenirken yürüdüğü matematiksel yolu da optimize edebiliriz.]]></summary></entry><entry><title type="html">Go ile Ters Proxy Yönetimi: Güvenli ve Hafif Ağ Geçitleri</title><link href="https://sonsuzus.github.io/posts/go-ile-ters-proxy-yonetimi-guvenli-ve-hafif-ag-gecitleri/" rel="alternate" type="text/html" title="Go ile Ters Proxy Yönetimi: Güvenli ve Hafif Ağ Geçitleri" /><published>2026-07-13T00:00:00+00:00</published><updated>2026-07-13T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/go-ile-ters-proxy-yonetimi-guvenli-ve-hafif-ag-gecitleri</id><content type="html" xml:base="https://sonsuzus.github.io/posts/go-ile-ters-proxy-yonetimi-guvenli-ve-hafif-ag-gecitleri/"><![CDATA[<p>Modern web sistemlerinde istemci ile servisler arasına akıllı bir kapı koymak çoğu zaman hayat kurtarır. Go ile yazılmış hafif bir ters proxy, gelen HTTP trafiğini uygun backend servisine yönlendirebilir, temel güvenlik kontrolleri yapabilir ve yükü birden fazla sunucuya dağıtabilir. Üstelik Go’nun standart kütüphanesindeki <code class="language-plaintext highlighter-rouge">net/http</code> ve <code class="language-plaintext highlighter-rouge">httputil</code> paketleri sayesinde bunu devasa framework’lere ihtiyaç duymadan kurabilirsiniz.
``</p>

<p>Ters proxy, istemcinin gerçek uygulama sunucularıyla doğrudan konuşmasını engelleyen aracı katmandır. İstemci <code class="language-plaintext highlighter-rouge">api.ornek.com</code> adresine istek atar; ters proxy bu isteği arkadaki <code class="language-plaintext highlighter-rouge">service-1</code>, <code class="language-plaintext highlighter-rouge">service-2</code> veya <code class="language-plaintext highlighter-rouge">service-3</code> gibi sunuculara iletir. Böylece güvenlik, gözlemlenebilirlik, önbellekleme, TLS sonlandırma ve yük dengeleme tek noktadan yönetilebilir.</p>

<p>Temel farkı şöyle özetleyebiliriz:</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Forward Proxy</th>
      <th>Reverse Proxy</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kimi temsil eder?</td>
      <td>İstemciyi</td>
      <td>Sunucuyu</td>
    </tr>
    <tr>
      <td>Kullanım amacı</td>
      <td>İnternete kontrollü çıkış</td>
      <td>Servislere kontrollü giriş</td>
    </tr>
    <tr>
      <td>Gizlenen taraf</td>
      <td>Kullanıcı/istemci</td>
      <td>Backend sunucular</td>
    </tr>
    <tr>
      <td>Örnek</td>
      <td>Kurumsal internet proxy’si</td>
      <td>API Gateway, Nginx, Traefik</td>
    </tr>
  </tbody>
</table>

<p>Yük dengelemenin mantığı ise basit ama kritiktir. Elimizde $n$ adet backend varsa ve gelen toplam istek sayısı $R$ ise ideal durumda her sunucunun yaklaşık yükü şu olur: $R_i \approx \frac{R}{n}$. Gerçekte CPU, bellek, ağ gecikmesi ve hata oranları farklı olduğundan bu dağılım her zaman eşit değildir. Bu yüzden round-robin, weighted round-robin veya least-connections gibi algoritmalar kullanılır.</p>

<table>
  <thead>
    <tr>
      <th>Algoritma</th>
      <th>Mantık</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Round Robin</td>
      <td>Sırayla dağıtır</td>
      <td>Basit ve hızlı</td>
      <td>Sunucu gücünü dikkate almaz</td>
    </tr>
    <tr>
      <td>Weighted Round Robin</td>
      <td>Ağırlığa göre dağıtır</td>
      <td>Güçlü sunucuya daha çok trafik verir</td>
      <td>Ağırlık ayarı gerekir</td>
    </tr>
    <tr>
      <td>Least Connections</td>
      <td>En az bağlantılıya yollar</td>
      <td>Dinamik yüke duyarlı</td>
      <td>Takip maliyeti vardır</td>
    </tr>
  </tbody>
</table>

<p>Go’da en yalın ters proxy örneği <code class="language-plaintext highlighter-rouge">httputil.NewSingleHostReverseProxy</code> ile yazılabilir. Aşağıdaki kod, gelen isteği tek bir backend’e aktarır; ayrıca <code class="language-plaintext highlighter-rouge">X-Forwarded-Host</code> başlığıyla orijinal host bilgisini korur.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="k">import</span> <span class="p">(</span>
    <span class="s">"log"</span>
    <span class="s">"net/http"</span>
    <span class="s">"net/http/httputil"</span>
    <span class="s">"net/url"</span>
<span class="p">)</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">target</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">url</span><span class="o">.</span><span class="n">Parse</span><span class="p">(</span><span class="s">"http://localhost:8081"</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
        <span class="n">log</span><span class="o">.</span><span class="n">Fatal</span><span class="p">(</span><span class="n">err</span><span class="p">)</span>
    <span class="p">}</span>

    <span class="n">proxy</span> <span class="o">:=</span> <span class="n">httputil</span><span class="o">.</span><span class="n">NewSingleHostReverseProxy</span><span class="p">(</span><span class="n">target</span><span class="p">)</span>

    <span class="n">originalDirector</span> <span class="o">:=</span> <span class="n">proxy</span><span class="o">.</span><span class="n">Director</span>
    <span class="n">proxy</span><span class="o">.</span><span class="n">Director</span> <span class="o">=</span> <span class="k">func</span><span class="p">(</span><span class="n">req</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">originalDirector</span><span class="p">(</span><span class="n">req</span><span class="p">)</span>
        <span class="n">req</span><span class="o">.</span><span class="n">Header</span><span class="o">.</span><span class="n">Set</span><span class="p">(</span><span class="s">"X-Forwarded-Host"</span><span class="p">,</span> <span class="n">req</span><span class="o">.</span><span class="n">Host</span><span class="p">)</span>
        <span class="n">req</span><span class="o">.</span><span class="n">Header</span><span class="o">.</span><span class="n">Set</span><span class="p">(</span><span class="s">"X-Gateway"</span><span class="p">,</span> <span class="s">"go-reverse-proxy"</span><span class="p">)</span>
    <span class="p">}</span>

    <span class="n">log</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="s">"Proxy :8080 üzerinde çalışıyor"</span><span class="p">)</span>
    <span class="n">log</span><span class="o">.</span><span class="n">Fatal</span><span class="p">(</span><span class="n">http</span><span class="o">.</span><span class="n">ListenAndServe</span><span class="p">(</span><span class="s">":8080"</span><span class="p">,</span> <span class="n">proxy</span><span class="p">))</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu kodda <code class="language-plaintext highlighter-rouge">Director</code>, isteğin backend’e gitmeden önce nasıl değiştirileceğini belirler. Örneğin path yeniden yazılabilir, header eklenebilir veya belirli istekler engellenebilir. Pratikte burada kimlik doğrulama, IP filtreleme ya da rate limit kontrolü de uygulanabilir.</p>

<p>Şimdi bunu küçük bir round-robin yük dengeleyiciye çevirelim:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="k">import</span> <span class="p">(</span>
    <span class="s">"log"</span>
    <span class="s">"net/http"</span>
    <span class="s">"net/http/httputil"</span>
    <span class="s">"net/url"</span>
    <span class="s">"sync/atomic"</span>
<span class="p">)</span>

<span class="k">type</span> <span class="n">Backend</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="n">URL</span>   <span class="o">*</span><span class="n">url</span><span class="o">.</span><span class="n">URL</span>
    <span class="n">Proxy</span> <span class="o">*</span><span class="n">httputil</span><span class="o">.</span><span class="n">ReverseProxy</span>
<span class="p">}</span>

<span class="k">type</span> <span class="n">LoadBalancer</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="n">backends</span> <span class="p">[]</span><span class="n">Backend</span>
    <span class="n">counter</span>  <span class="kt">uint64</span>
<span class="p">}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">lb</span> <span class="o">*</span><span class="n">LoadBalancer</span><span class="p">)</span> <span class="n">ServeHTTP</span><span class="p">(</span><span class="n">w</span> <span class="n">http</span><span class="o">.</span><span class="n">ResponseWriter</span><span class="p">,</span> <span class="n">r</span> <span class="o">*</span><span class="n">http</span><span class="o">.</span><span class="n">Request</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">index</span> <span class="o">:=</span> <span class="n">atomic</span><span class="o">.</span><span class="n">AddUint64</span><span class="p">(</span><span class="o">&amp;</span><span class="n">lb</span><span class="o">.</span><span class="n">counter</span><span class="p">,</span> <span class="m">1</span><span class="p">)</span> <span class="o">%</span> <span class="kt">uint64</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">lb</span><span class="o">.</span><span class="n">backends</span><span class="p">))</span>
    <span class="n">backend</span> <span class="o">:=</span> <span class="n">lb</span><span class="o">.</span><span class="n">backends</span><span class="p">[</span><span class="n">index</span><span class="p">]</span>
    <span class="n">r</span><span class="o">.</span><span class="n">Header</span><span class="o">.</span><span class="n">Set</span><span class="p">(</span><span class="s">"X-Selected-Backend"</span><span class="p">,</span> <span class="n">backend</span><span class="o">.</span><span class="n">URL</span><span class="o">.</span><span class="n">String</span><span class="p">())</span>
    <span class="n">backend</span><span class="o">.</span><span class="n">Proxy</span><span class="o">.</span><span class="n">ServeHTTP</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">addresses</span> <span class="o">:=</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span>
        <span class="s">"http://localhost:8081"</span><span class="p">,</span>
        <span class="s">"http://localhost:8082"</span><span class="p">,</span>
        <span class="s">"http://localhost:8083"</span><span class="p">,</span>
    <span class="p">}</span>

    <span class="n">lb</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="n">LoadBalancer</span><span class="p">{}</span>
    <span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">addr</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">addresses</span> <span class="p">{</span>
        <span class="n">u</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">url</span><span class="o">.</span><span class="n">Parse</span><span class="p">(</span><span class="n">addr</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
            <span class="n">log</span><span class="o">.</span><span class="n">Fatal</span><span class="p">(</span><span class="n">err</span><span class="p">)</span>
        <span class="p">}</span>
        <span class="n">lb</span><span class="o">.</span><span class="n">backends</span> <span class="o">=</span> <span class="nb">append</span><span class="p">(</span><span class="n">lb</span><span class="o">.</span><span class="n">backends</span><span class="p">,</span> <span class="n">Backend</span><span class="p">{</span>
            <span class="n">URL</span><span class="o">:</span>   <span class="n">u</span><span class="p">,</span>
            <span class="n">Proxy</span><span class="o">:</span> <span class="n">httputil</span><span class="o">.</span><span class="n">NewSingleHostReverseProxy</span><span class="p">(</span><span class="n">u</span><span class="p">),</span>
        <span class="p">})</span>
    <span class="p">}</span>

    <span class="n">log</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="s">"Load balancer :8080 üzerinde hazır"</span><span class="p">)</span>
    <span class="n">log</span><span class="o">.</span><span class="n">Fatal</span><span class="p">(</span><span class="n">http</span><span class="o">.</span><span class="n">ListenAndServe</span><span class="p">(</span><span class="s">":8080"</span><span class="p">,</span> <span class="n">lb</span><span class="p">))</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">atomic.AddUint64</code>, eşzamanlı isteklerde sayaç yarışını engeller. Her istek farklı backend’e gönderilir. Matematiksel olarak seçim <code class="language-plaintext highlighter-rouge">index = counter \bmod n</code> şeklindedir. Yani sayaç büyür, backend listesi döngüsel biçimde kullanılır.</p>

<p>Güvenlik tarafında birkaç noktayı atlamamak gerekir. Proxy’niz dış dünyaya açık olduğu için header spoofing, yavaş istek saldırıları ve büyük body gönderimleriyle karşılaşabilir. <code class="language-plaintext highlighter-rouge">http.Server</code> yapılandırmasında timeout değerleri vermek iyi bir başlangıçtır.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">server</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="n">http</span><span class="o">.</span><span class="n">Server</span><span class="p">{</span>
    <span class="n">Addr</span><span class="o">:</span>              <span class="s">":8080"</span><span class="p">,</span>
    <span class="n">Handler</span><span class="o">:</span>           <span class="n">lb</span><span class="p">,</span>
    <span class="n">ReadHeaderTimeout</span><span class="o">:</span> <span class="m">5</span> <span class="o">*</span> <span class="n">time</span><span class="o">.</span><span class="n">Second</span><span class="p">,</span>
    <span class="n">ReadTimeout</span><span class="o">:</span>       <span class="m">10</span> <span class="o">*</span> <span class="n">time</span><span class="o">.</span><span class="n">Second</span><span class="p">,</span>
    <span class="n">WriteTimeout</span><span class="o">:</span>      <span class="m">15</span> <span class="o">*</span> <span class="n">time</span><span class="o">.</span><span class="n">Second</span><span class="p">,</span>
    <span class="n">IdleTimeout</span><span class="o">:</span>       <span class="m">60</span> <span class="o">*</span> <span class="n">time</span><span class="o">.</span><span class="n">Second</span><span class="p">,</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Sonuç olarak Go, ters proxy yazmak için şaşırtıcı derecede güçlü bir araçtır. Küçük bir kod tabanıyla trafik yönlendirme, servis gizleme ve basit yük dengeleme yapabilirsiniz. Üretim ortamında buna health check, loglama, metrik toplama, TLS ve circuit breaker eklediğinizde kendi mini API gateway’inizi inşa etmiş olursunuz. Kısacası: Go ile ağ geçidi yazmak, hem öğretici hem de oldukça keyifli bir mühendislik egzersizidir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="go" /><category term="reverse-proxy" /><category term="load-balancing" /><category term="networking" /><summary type="html"><![CDATA[Modern web sistemlerinde istemci ile servisler arasına akıllı bir kapı koymak çoğu zaman hayat kurtarır. Go ile yazılmış hafif bir ters proxy, gelen HTTP trafiğini uygun backend servisine yönlendirebilir, temel güvenlik kontrolleri yapabilir ve yükü birden fazla sunucuya dağıtabilir. Üstelik Go’nun standart kütüphanesindeki net/http ve httputil paketleri sayesinde bunu devasa framework’lere ihtiyaç duymadan kurabilirsiniz.]]></summary></entry><entry><title type="html">SQL ile Mitolojik Soy Ağaçları: Tanrıları, Kahramanları ve Ejderhaları Modelle</title><link href="https://sonsuzus.github.io/posts/sql-ile-mitolojik-soy-agaclari-tanrilari-kahramanlari-ve-ejderhalari-modelle/" rel="alternate" type="text/html" title="SQL ile Mitolojik Soy Ağaçları: Tanrıları, Kahramanları ve Ejderhaları Modelle" /><published>2026-07-13T00:00:00+00:00</published><updated>2026-07-13T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/sql-ile-mitolojik-soy-agaclari-tanrilari-kahramanlari-ve-ejderhalari-modelle</id><content type="html" xml:base="https://sonsuzus.github.io/posts/sql-ile-mitolojik-soy-agaclari-tanrilari-kahramanlari-ve-ejderhalari-modelle/"><![CDATA[<p>Mitoloji, veritabanı tasarımcıları için adeta boss seviyesi bir problemdir: Zeus hem baba, hem eş, hem de bazen kuğu kılığına giren kaotik bir kayıt üreticisidir. İskandinavlarda Loki’nin aile ilişkileri türler arası sınırları zorlar; Türk destanlarında soy, kutsal kurt ya da göksel kökenlerle birleşir. Bu yüzden antik tanrılar ve destan karakterleri için bir SQL soy ağacı kurmak, sadece tablo açmak değil, belirsizlikleri, kültürel kaynakları ve çoklu ilişki tiplerini modellemektir.
``</p>

<p>Temel fikir şudur: Mitolojik karakterleri düğüm, aralarındaki bağları kenar kabul ederiz. Yani elimizde küçük bir grafik vardır: $G=(V,E)$. Burada $V$ kişiler, tanrılar, canavarlar veya yarı tanrılar; $E$ ise ebeveynlik, eşlik, kardeşlik, yaratılma ya da lanetlenme gibi ilişkilerdir. Klasik soy ağacında ilişki genelde $parent \rightarrow child$ biçimindedir; fakat mitolojide aynı varlık birden fazla kaynağa göre farklı ebeveynlere sahip olabilir. Bu nedenle kaynak bilgisini ayrı tutmak altın kuraldır.</p>

<table>
  <thead>
    <tr>
      <th>Modelleme Yaklaşımı</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
      <th>Mitolojiye Uygunluk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tek tabloda anne_id, baba_id</td>
      <td>Basit ve hızlı</td>
      <td>Tanrısal doğum, belirsizlik ve çoklu kaynak zayıf kalır</td>
      <td>Düşük</td>
    </tr>
    <tr>
      <td>İlişki tablosu</td>
      <td>Esnek, çoklu ebeveyn destekler</td>
      <td>Sorgular biraz karmaşıklaşır</td>
      <td>Yüksek</td>
    </tr>
    <tr>
      <td>Grafik veritabanı</td>
      <td>Doğal akrabalık gezintisi</td>
      <td>SQL ekosisteminden uzaklaşabilir</td>
      <td>Çok yüksek</td>
    </tr>
  </tbody>
</table>

<p>SQL tarafında ilişkisel ama grafik tadında bir şema kurabiliriz:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">beings</span> <span class="p">(</span>
  <span class="n">id</span> <span class="nb">INTEGER</span> <span class="k">PRIMARY</span> <span class="k">KEY</span><span class="p">,</span>
  <span class="n">name</span> <span class="nb">TEXT</span> <span class="k">NOT</span> <span class="k">NULL</span><span class="p">,</span>
  <span class="n">culture</span> <span class="nb">TEXT</span> <span class="k">NOT</span> <span class="k">NULL</span><span class="p">,</span>
  <span class="n">being_type</span> <span class="nb">TEXT</span> <span class="k">CHECK</span> <span class="p">(</span><span class="n">being_type</span> <span class="k">IN</span> <span class="p">(</span><span class="s1">'god'</span><span class="p">,</span><span class="s1">'human'</span><span class="p">,</span><span class="s1">'hero'</span><span class="p">,</span><span class="s1">'monster'</span><span class="p">,</span><span class="s1">'titan'</span><span class="p">,</span><span class="s1">'spirit'</span><span class="p">)),</span>
  <span class="n">notes</span> <span class="nb">TEXT</span>
<span class="p">);</span>

<span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">sources</span> <span class="p">(</span>
  <span class="n">id</span> <span class="nb">INTEGER</span> <span class="k">PRIMARY</span> <span class="k">KEY</span><span class="p">,</span>
  <span class="n">title</span> <span class="nb">TEXT</span> <span class="k">NOT</span> <span class="k">NULL</span><span class="p">,</span>
  <span class="n">tradition</span> <span class="nb">TEXT</span><span class="p">,</span>
  <span class="n">reliability_score</span> <span class="nb">NUMERIC</span> <span class="k">CHECK</span> <span class="p">(</span><span class="n">reliability_score</span> <span class="k">BETWEEN</span> <span class="mi">0</span> <span class="k">AND</span> <span class="mi">1</span><span class="p">)</span>
<span class="p">);</span>

<span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">relationships</span> <span class="p">(</span>
  <span class="n">id</span> <span class="nb">INTEGER</span> <span class="k">PRIMARY</span> <span class="k">KEY</span><span class="p">,</span>
  <span class="n">from_id</span> <span class="nb">INTEGER</span> <span class="k">REFERENCES</span> <span class="n">beings</span><span class="p">(</span><span class="n">id</span><span class="p">),</span>
  <span class="n">to_id</span> <span class="nb">INTEGER</span> <span class="k">REFERENCES</span> <span class="n">beings</span><span class="p">(</span><span class="n">id</span><span class="p">),</span>
  <span class="n">relation_type</span> <span class="nb">TEXT</span> <span class="k">NOT</span> <span class="k">NULL</span><span class="p">,</span>
  <span class="n">source_id</span> <span class="nb">INTEGER</span> <span class="k">REFERENCES</span> <span class="n">sources</span><span class="p">(</span><span class="n">id</span><span class="p">),</span>
  <span class="n">certainty</span> <span class="nb">NUMERIC</span> <span class="k">CHECK</span> <span class="p">(</span><span class="n">certainty</span> <span class="k">BETWEEN</span> <span class="mi">0</span> <span class="k">AND</span> <span class="mi">1</span><span class="p">)</span>
<span class="p">);</span>
</code></pre></div></div>

<p>Bu yapıda <code class="language-plaintext highlighter-rouge">relationships</code> tablosu ana sahnedir. Örneğin <code class="language-plaintext highlighter-rouge">from_id = Zeus</code>, <code class="language-plaintext highlighter-rouge">to_id = Athena</code>, <code class="language-plaintext highlighter-rouge">relation_type = parent</code> diyebiliriz. Ancak Athena’nın doğumu sıradan olmadığı için <code class="language-plaintext highlighter-rouge">notes</code> veya ayrı bir olay tablosu ile kafadan doğma gibi anlatıları saklayabiliriz. Matematiksel olarak her ilişkinin ağırlığı $w \in [0,1]$ olabilir; burada $w$ kesinlik değeridir. Böylece tartışmalı soylar için veritabanı dogmatik davranmaz.</p>

<p>Örnek veri ekleyelim:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">INSERT</span> <span class="k">INTO</span> <span class="n">beings</span> <span class="k">VALUES</span>
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'Zeus'</span><span class="p">,</span> <span class="s1">'Greek'</span><span class="p">,</span> <span class="s1">'god'</span><span class="p">,</span> <span class="s1">'Olympian sky god'</span><span class="p">),</span>
<span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="s1">'Athena'</span><span class="p">,</span> <span class="s1">'Greek'</span><span class="p">,</span> <span class="s1">'god'</span><span class="p">,</span> <span class="s1">'Born from Zeus according to common tradition'</span><span class="p">),</span>
<span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="s1">'Odin'</span><span class="p">,</span> <span class="s1">'Norse'</span><span class="p">,</span> <span class="s1">'god'</span><span class="p">,</span> <span class="s1">'All-father figure'</span><span class="p">),</span>
<span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="s1">'Thor'</span><span class="p">,</span> <span class="s1">'Norse'</span><span class="p">,</span> <span class="s1">'god'</span><span class="p">,</span> <span class="s1">'Thunder god'</span><span class="p">),</span>
<span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="s1">'Loki'</span><span class="p">,</span> <span class="s1">'Norse'</span><span class="p">,</span> <span class="s1">'god'</span><span class="p">,</span> <span class="s1">'Trickster with complex kinship'</span><span class="p">);</span>

<span class="k">INSERT</span> <span class="k">INTO</span> <span class="n">sources</span> <span class="k">VALUES</span>
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'Theogony'</span><span class="p">,</span> <span class="s1">'Greek'</span><span class="p">,</span> <span class="mi">0</span><span class="p">.</span><span class="mi">90</span><span class="p">),</span>
<span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="s1">'Poetic Edda'</span><span class="p">,</span> <span class="s1">'Norse'</span><span class="p">,</span> <span class="mi">0</span><span class="p">.</span><span class="mi">85</span><span class="p">);</span>

<span class="k">INSERT</span> <span class="k">INTO</span> <span class="n">relationships</span> <span class="k">VALUES</span>
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="s1">'parent'</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">.</span><span class="mi">95</span><span class="p">),</span>
<span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="s1">'parent'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">.</span><span class="mi">90</span><span class="p">),</span>
<span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="s1">'ally'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">.</span><span class="mi">60</span><span class="p">);</span>
</code></pre></div></div>

<p>Asıl eğlence recursive CTE ile başlar. Bir karakterin tüm atalarını bulmak için:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">WITH</span> <span class="k">RECURSIVE</span> <span class="n">ancestry</span><span class="p">(</span><span class="n">depth</span><span class="p">,</span> <span class="n">ancestor_id</span><span class="p">,</span> <span class="n">descendant_id</span><span class="p">)</span> <span class="k">AS</span> <span class="p">(</span>
  <span class="k">SELECT</span> <span class="mi">1</span><span class="p">,</span> <span class="n">from_id</span><span class="p">,</span> <span class="n">to_id</span>
  <span class="k">FROM</span> <span class="n">relationships</span>
  <span class="k">WHERE</span> <span class="n">relation_type</span> <span class="o">=</span> <span class="s1">'parent'</span> <span class="k">AND</span> <span class="n">to_id</span> <span class="o">=</span> <span class="mi">2</span>

  <span class="k">UNION</span> <span class="k">ALL</span>

  <span class="k">SELECT</span> <span class="n">a</span><span class="p">.</span><span class="n">depth</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">r</span><span class="p">.</span><span class="n">from_id</span><span class="p">,</span> <span class="n">a</span><span class="p">.</span><span class="n">descendant_id</span>
  <span class="k">FROM</span> <span class="n">relationships</span> <span class="n">r</span>
  <span class="k">JOIN</span> <span class="n">ancestry</span> <span class="n">a</span> <span class="k">ON</span> <span class="n">r</span><span class="p">.</span><span class="n">to_id</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">ancestor_id</span>
  <span class="k">WHERE</span> <span class="n">r</span><span class="p">.</span><span class="n">relation_type</span> <span class="o">=</span> <span class="s1">'parent'</span>
<span class="p">)</span>
<span class="k">SELECT</span> <span class="n">depth</span><span class="p">,</span> <span class="n">b</span><span class="p">.</span><span class="n">name</span> <span class="k">AS</span> <span class="n">ancestor</span>
<span class="k">FROM</span> <span class="n">ancestry</span>
<span class="k">JOIN</span> <span class="n">beings</span> <span class="n">b</span> <span class="k">ON</span> <span class="n">b</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="n">ancestry</span><span class="p">.</span><span class="n">ancestor_id</span><span class="p">;</span>
</code></pre></div></div>

<p>Bu sorgu Athena’nın ebeveyninden başlayıp yukarı doğru tırmanır. <code class="language-plaintext highlighter-rouge">depth</code> değeri nesil uzaklığını gösterir: $depth=1$ ebeveyn, $depth=2$ büyükanne veya büyükbaba gibi düşünülebilir. Eğer döngü ihtimali varsa, yani bir mitolojik anlatıda karakter kendi soyuna garip şekilde bağlanıyorsa, ziyaret edilen düğümleri takip eden ek bir kolon kullanmak gerekir.</p>

<table>
  <thead>
    <tr>
      <th>İlişki Türü</th>
      <th style="text-align: right">Yönlü mü?</th>
      <th>Örnek</th>
      <th>Sorgu Notu</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>parent</td>
      <td style="text-align: right">Evet</td>
      <td>Odin → Thor</td>
      <td>Atalık sorgularında kullanılır</td>
    </tr>
    <tr>
      <td>spouse</td>
      <td style="text-align: right">Genelde çift yönlü</td>
      <td>Hera ↔ Zeus</td>
      <td>İki kayıt veya normalize edilmiş çift gerekir</td>
    </tr>
    <tr>
      <td>sibling</td>
      <td style="text-align: right">Türetilmiş olabilir</td>
      <td>Apollo ↔ Artemis</td>
      <td>Aynı ebeveynden hesaplanabilir</td>
    </tr>
    <tr>
      <td>created_by</td>
      <td style="text-align: right">Evet</td>
      <td>İnsan → Prometheus</td>
      <td>Soy değil, yaratılış bağıdır</td>
    </tr>
  </tbody>
</table>

<p>Kültürler arası bağlantı kurarken aynı karakterin varyantlarını da düşünmeliyiz. Roma Jüpiter’i ile Yunan Zeus’u birebir aynı kayıt mı olmalı, yoksa <code class="language-plaintext highlighter-rouge">equivalent_to</code> ilişkisiyle mi bağlanmalı? Genelde ikinci yaklaşım daha sağlıklıdır; çünkü $Zeus \neq Jupiter$ demek tarihsel bağlamı korur, ama <code class="language-plaintext highlighter-rouge">equivalent_to</code> ile benzerliği sorgulanabilir yapar.</p>

<p>Sonuçta bu proje, SQL öğrenmek için harika bir oyun alanıdır. Normalizasyon, yabancı anahtarlar, çoktan çoğa ilişkiler, recursive sorgular ve belirsizlik modelleme aynı kazanda kaynar. Üstelik test verisi sıkıcı müşteri tabloları değil; titanlar, yarı tanrılar, devler ve kader tanrıçalarıdır. Bir sonraki adım olarak ilişkilere tarihsel dönem, coğrafya ve anlatı varyantı ekleyip kendi mitolojik bilgi grafiğinizi küçük bir dijital Olimpos’a dönüştürebilirsiniz.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="SQL" /><category term="veritabanı tasarımı" /><category term="mitoloji" /><category term="recursive CTE" /><summary type="html"><![CDATA[Mitoloji, veritabanı tasarımcıları için adeta boss seviyesi bir problemdir: Zeus hem baba, hem eş, hem de bazen kuğu kılığına giren kaotik bir kayıt üreticisidir. İskandinavlarda Loki’nin aile ilişkileri türler arası sınırları zorlar; Türk destanlarında soy, kutsal kurt ya da göksel kökenlerle birleşir. Bu yüzden antik tanrılar ve destan karakterleri için bir SQL soy ağacı kurmak, sadece tablo açmak değil, belirsizlikleri, kültürel kaynakları ve çoklu ilişki tiplerini modellemektir.]]></summary></entry><entry><title type="html">C Dilinin Minimalizmi ve İşletim Sistemleri: Belleğe Dokunan Kodun Büyüsü</title><link href="https://sonsuzus.github.io/posts/c-dilinin-minimalizmi-ve-isletim-sistemleri-bellege-dokunan-kodun-buyusu/" rel="alternate" type="text/html" title="C Dilinin Minimalizmi ve İşletim Sistemleri: Belleğe Dokunan Kodun Büyüsü" /><published>2026-07-12T00:00:00+00:00</published><updated>2026-07-12T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/c-dilinin-minimalizmi-ve-isletim-sistemleri-bellege-dokunan-kodun-buyusu</id><content type="html" xml:base="https://sonsuzus.github.io/posts/c-dilinin-minimalizmi-ve-isletim-sistemleri-bellege-dokunan-kodun-buyusu/"><![CDATA[<p>C dili, modern bilişimin perde arkasındaki sessiz kahramanlardan biridir. Bugün web uygulamaları, yapay zekâ servisleri ve oyun motorları konuşulurken, tüm bu katmanların altında hâlâ donanıma yakın, sade ve tahmin edilebilir bir dil yatar. C’nin minimalizmi; az anahtar kelime, doğrudan bellek erişimi ve çalışma zamanında sihir yapmayan yapısıyla özellikle işletim sistemi çekirdekleri için idealdir.
``
Bir işletim sistemi çekirdeği, donanım ile uygulamalar arasındaki en kritik aracıdır. Klavyeden gelen kesme, diske yazılan veri, RAM’de ayrılan sayfa veya işlemci modları gibi konular kernel tarafından yönetilir. C burada devreye girer çünkü ne yaptığını saklamaz. Bir pointer, gerçekten bir adrestir; bir struct, bellekte belirli bir düzendir; bir volatile değişken, derleyiciye bu değerin dış dünya tarafından değişebileceğini söyler.</p>

<p>C’nin minimalizmini anlamak için onu daha yüksek seviyeli dillerle karşılaştırmak faydalıdır:</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>C</th>
      <th>Yüksek Seviyeli Diller</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Bellek yönetimi</td>
      <td>Manuel</td>
      <td>Çoğunlukla otomatik</td>
    </tr>
    <tr>
      <td>Donanıma erişim</td>
      <td>Doğrudan</td>
      <td>Soyut katmanlarla</td>
    </tr>
    <tr>
      <td>Çalışma zamanı</td>
      <td>Çok küçük veya yok</td>
      <td>Genellikle büyük runtime</td>
    </tr>
    <tr>
      <td>Tahmin edilebilirlik</td>
      <td>Yüksek</td>
      <td>Dil ve VM davranışına bağlı</td>
    </tr>
    <tr>
      <td>Kernel geliştirme</td>
      <td>Çok uygun</td>
      <td>Genellikle uygun değil</td>
    </tr>
  </tbody>
</table>

<p>Bellek adresleriyle konuşmak, C’nin en güçlü ama en dikkat isteyen tarafıdır. Örneğin 32 bitlik bir sistemde adres uzayı teorik olarak $2^{32}$ bayttır, yani yaklaşık 4 GB. Bir aygıtın kontrol register’ı belirli bir adrese eşlenmişse, kernel bu adrese yazarak aygıta komut verebilir. Buradaki temel fikir şudur: $Adres = Taban + Ofset$. Basit görünüyor, ama bu denklem ekran kartından zamanlayıcıya kadar pek çok donanım etkileşiminin temelidir.</p>

<p>Aşağıdaki örnek, bellek eşlemeli bir donanım register’ına erişim mantığını gösterir. Bu kod gerçek bir cihaz sürücüsünün sadeleştirilmiş halidir:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdint.h&gt;</span><span class="cp">
</span>
<span class="cp">#define TIMER_BASE 0x40000000u
#define TIMER_CTRL (*(volatile uint32_t *)(TIMER_BASE + 0x00))
#define TIMER_COUNT (*(volatile uint32_t *)(TIMER_BASE + 0x04))
</span>
<span class="kt">void</span> <span class="nf">timer_start</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">TIMER_COUNT</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">;</span>      <span class="c1">// Sayaç başlangıç değeri</span>
    <span class="n">TIMER_CTRL</span> <span class="o">=</span> <span class="mh">0x1</span><span class="p">;</span>        <span class="c1">// Timer etkinleştir</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">timer_stop</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">TIMER_CTRL</span> <span class="o">=</span> <span class="mh">0x0</span><span class="p">;</span>        <span class="c1">// Timer durdur</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">volatile</code> kritik önemdedir. Derleyici normalde gereksiz gördüğü bellek okumalarını veya yazmalarını optimize edebilir. Ancak donanım register’ları sıradan değişken değildir; değerleri dış dünyadan değişebilir. <code class="language-plaintext highlighter-rouge">volatile</code>, derleyiciye şu mesajı verir: Bu adrese gerçekten git, okuma veya yazmayı atlama.</p>

<p>Kernel modülleri yazarken yalnızca C bilmek yetmez; işlemci mimarisini de tanımak gerekir. Kullanıcı modu ve çekirdek modu ayrımı, sistem çağrıları, kesmeler ve sayfalama mekanizması bu dünyanın temel taşlarıdır.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Ne İşe Yarar?</th>
      <th>C ile İlişkisi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Pointer</td>
      <td>Bellek adresi tutar</td>
      <td>Donanıma erişimin anahtarıdır</td>
    </tr>
    <tr>
      <td>Struct</td>
      <td>Veriyi düzenli paketler</td>
      <td>Register haritalarında kullanılır</td>
    </tr>
    <tr>
      <td>Bit işlemleri</td>
      <td>Bayrakları yönetir</td>
      <td>Kontrol register’ları için şarttır</td>
    </tr>
    <tr>
      <td>Inline assembly</td>
      <td>Özel CPU komutu çalıştırır</td>
      <td>C’nin yetmediği yerde devreye girer</td>
    </tr>
  </tbody>
</table>

<p>Bit işlemleri kernel kodunda neredeyse günlük ekmek gibidir. Bir register’ın yalnızca üçüncü bitini açmak istiyorsanız tüm değeri değiştirmek yerine maskeleme yaparsınız. Matematiksel olarak bir bit maskesi $2^n$ ile temsil edilebilir. Örneğin üçüncü bit için maske $2^3 = 8$ olur.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define ENABLE_BIT (1u &lt;&lt; 3)
</span>
<span class="kt">void</span> <span class="nf">enable_device</span><span class="p">(</span><span class="k">volatile</span> <span class="kt">uint32_t</span> <span class="o">*</span><span class="n">reg</span><span class="p">)</span> <span class="p">{</span>
    <span class="o">*</span><span class="n">reg</span> <span class="o">|=</span> <span class="n">ENABLE_BIT</span><span class="p">;</span>   <span class="c1">// Sadece ilgili biti 1 yap</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">disable_device</span><span class="p">(</span><span class="k">volatile</span> <span class="kt">uint32_t</span> <span class="o">*</span><span class="n">reg</span><span class="p">)</span> <span class="p">{</span>
    <span class="o">*</span><span class="n">reg</span> <span class="o">&amp;=</span> <span class="o">~</span><span class="n">ENABLE_BIT</span><span class="p">;</span>  <span class="c1">// Sadece ilgili biti 0 yap</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu küçük örnekler, C’nin neden hâlâ kernel dünyasında yaşadığını anlatır. Dil sizi korumaz; ama size engel de olmaz. Yanlış adrese yazarsanız sistem çökebilir, fakat doğru adrese doğru biti yazarsanız donanım sizinle konuşmaya başlar. Bu biraz eski tip bir radyo tamirciliği gibidir: kablolar, sinyaller, küçük tornavidalar ve bolca dikkat.</p>

<p>Sonuç olarak C’nin minimalizmi bir eksiklik değil, bilinçli bir tasarımdır. İşletim sistemleri gibi donanıma en yakın yazılımlarda fazladan soyutlama bazen lüks değil, risktir. C; pointer’ları, bit işlemleri, sade veri yapıları ve düşük seviye kontrol gücüyle modern bilgisayarların temelini anlamak isteyenler için hâlâ en iyi laboratuvarlardan biridir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="C" /><category term="işletim sistemleri" /><category term="kernel" /><category term="bellek yönetimi" /><summary type="html"><![CDATA[C dili, modern bilişimin perde arkasındaki sessiz kahramanlardan biridir. Bugün web uygulamaları, yapay zekâ servisleri ve oyun motorları konuşulurken, tüm bu katmanların altında hâlâ donanıma yakın, sade ve tahmin edilebilir bir dil yatar. C’nin minimalizmi; az anahtar kelime, doğrudan bellek erişimi ve çalışma zamanında sihir yapmayan yapısıyla özellikle işletim sistemi çekirdekleri için idealdir.]]></summary></entry><entry><title type="html">JavaScript ve NFC Etkileşimi: Web NFC ile Cebe Dokunan Uygulamalar</title><link href="https://sonsuzus.github.io/posts/javascript-ve-nfc-etkilesimi-web-nfc-ile-cebe-dokunan-uygulamalar/" rel="alternate" type="text/html" title="JavaScript ve NFC Etkileşimi: Web NFC ile Cebe Dokunan Uygulamalar" /><published>2026-07-12T00:00:00+00:00</published><updated>2026-07-12T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/javascript-ve-nfc-etkilesimi-web-nfc-ile-cebe-dokunan-uygulamalar</id><content type="html" xml:base="https://sonsuzus.github.io/posts/javascript-ve-nfc-etkilesimi-web-nfc-ile-cebe-dokunan-uygulamalar/"><![CDATA[<p>Telefonunuzu bir etikete yaklaştırıp kapıyı açmak, Wi-Fi bilgisini almak ya da bir ürünün bakım geçmişini okumak kulağa biraz sihir gibi gelir; ama aslında sahnede NFC ve JavaScript vardır. Modern Android tarayıcılarında Web NFC API sayesinde web uygulamaları, yakın alan iletişimi sensörleriyle veri okuyup yazabilir. Yani bazen bir buton, bazen de 3 cm mesafe bütün deneyimi değiştirir.
``</p>

<p>NFC, Near Field Communication ifadesinin kısaltmasıdır ve çok kısa mesafede çalışan kablosuz iletişim teknolojisidir. Genellikle $d ≤ 4cm$ gibi yakın bir aralıkta anlamlıdır. Bunun sebebi güvenlik kadar fiziksel çalışma mantığıdır: NFC, radyo dalgasından çok manyetik alan eşleşmesine dayanır. Mesafe arttıkça alan etkisi yaklaşık $P ≈ 1/r^3$ gibi hızlı azalır; yani etiketi masanın öbür ucundan okumaya çalışmak, kedinize SQL öğretmeye benzer: teorik olarak konuşulur, pratikte zordur.</p>

<p>Web NFC tarafında ana karakterimiz <code class="language-plaintext highlighter-rouge">NDEFReader</code> sınıfıdır. NDEF, NFC Data Exchange Format anlamına gelir. Etiketin içinde metin, URL, MIME verisi veya uygulamaya özel kayıtlar saklanabilir. JavaScript burada donanıma doğrudan hükmetmez; tarayıcı, güvenlik izinleri ve işletim sistemi üzerinden kontrollü bir köprü kurar.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>NFC</th>
      <th>QR Kod</th>
      <th>Bluetooth</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Mesafe</td>
      <td>Çok kısa</td>
      <td>Kamera görüşü kadar</td>
      <td>Daha uzun</td>
    </tr>
    <tr>
      <td>Kullanıcı eylemi</td>
      <td>Yaklaştırma</td>
      <td>Kamerayla tarama</td>
      <td>Eşleştirme gerekebilir</td>
    </tr>
    <tr>
      <td>Veri yazma</td>
      <td>Desteklenir</td>
      <td>Basılıysa zordur</td>
      <td>Cihaza bağlı</td>
    </tr>
    <tr>
      <td>Web entegrasyonu</td>
      <td>Web NFC ile mümkün</td>
      <td>Çok yaygın</td>
      <td>Web Bluetooth ile mümkün</td>
    </tr>
  </tbody>
</table>

<p>Web NFC kullanırken üç önemli koşul vardır: HTTPS üzerinde çalışmak, kullanıcıdan izin almak ve destekleyen bir tarayıcı kullanmak. Masaüstünde veya iOS Safari tarafında destek sınırlı olabilir. Bu yüzden üretim uygulamalarında özellik kontrolü yapmak şarttır.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if </span><span class="p">(</span><span class="dl">'</span><span class="s1">NDEFReader</span><span class="dl">'</span> <span class="k">in</span> <span class="nb">window</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Bu cihaz Web NFC destekliyor.</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">NFC desteklenmiyor, alternatif akış göster.</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu küçük kontrol, uygulamanın panik butonudur. Destek yoksa kullanıcıya QR kod, manuel kod girişi veya Bluetooth gibi alternatifler sunabilirsiniz. İyi kullanıcı deneyimi, sadece çalışan cihazı değil, çalışmayan senaryoyu da düşünür.</p>

<p>Bir NFC etiketi okumak için <code class="language-plaintext highlighter-rouge">scan()</code> metodu kullanılır. Tarayıcı izin penceresi gösterebilir ve kullanıcı cihazını etikete yaklaştırdığında <code class="language-plaintext highlighter-rouge">reading</code> olayı tetiklenir.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">reader</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">NDEFReader</span><span class="p">();</span>

<span class="k">async</span> <span class="kd">function</span> <span class="nf">startScan</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">try</span> <span class="p">{</span>
    <span class="k">await</span> <span class="nx">reader</span><span class="p">.</span><span class="nf">scan</span><span class="p">();</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">NFC tarama başladı.</span><span class="dl">'</span><span class="p">);</span>

    <span class="nx">reader</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">reading</span><span class="dl">'</span><span class="p">,</span> <span class="nx">event</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="kd">const</span> <span class="nx">decoder</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextDecoder</span><span class="p">();</span>

      <span class="k">for </span><span class="p">(</span><span class="kd">const</span> <span class="nx">record</span> <span class="k">of</span> <span class="nx">event</span><span class="p">.</span><span class="nx">message</span><span class="p">.</span><span class="nx">records</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if </span><span class="p">(</span><span class="nx">record</span><span class="p">.</span><span class="nx">recordType</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">text</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
          <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Okunan metin:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">decoder</span><span class="p">.</span><span class="nf">decode</span><span class="p">(</span><span class="nx">record</span><span class="p">.</span><span class="nx">data</span><span class="p">));</span>
        <span class="p">}</span>
      <span class="p">}</span>
    <span class="p">});</span>
  <span class="p">}</span> <span class="k">catch </span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Tarama hatası:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada kodun yaptığı iş basit ama güçlüdür: okuyucu başlatılır, etiket algılanınca mesaj kayıtları dolaşılır ve metin verisi çözümlenir. NFC verisi ham baytlar halinde geldiği için <code class="language-plaintext highlighter-rouge">TextDecoder</code> kullanmak gerekir. Bu noktada JavaScript, küçük bir tercüman gibi davranır.</p>

<p>Yazma işlemi de benzer şekilde yapılır. Örneğin bir müze uygulaması, sergi salonundaki NFC etiketine eser kimliği yazabilir.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">async</span> <span class="kd">function</span> <span class="nf">writeTag</span><span class="p">()</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">writer</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">NDEFReader</span><span class="p">();</span>

  <span class="k">try</span> <span class="p">{</span>
    <span class="k">await</span> <span class="nx">writer</span><span class="p">.</span><span class="nf">write</span><span class="p">({</span>
      <span class="na">records</span><span class="p">:</span> <span class="p">[</span>
        <span class="p">{</span>
          <span class="na">recordType</span><span class="p">:</span> <span class="dl">'</span><span class="s1">text</span><span class="dl">'</span><span class="p">,</span>
          <span class="na">data</span><span class="p">:</span> <span class="dl">'</span><span class="s1">eser:van-gogh-1889</span><span class="dl">'</span>
        <span class="p">}</span>
      <span class="p">]</span>
    <span class="p">});</span>

    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Etikete veri yazıldı.</span><span class="dl">'</span><span class="p">);</span>
  <span class="p">}</span> <span class="k">catch </span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="dl">'</span><span class="s1">Yazma başarısız:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Elbette her etikete sonsuz veri yazamayız. NFC etiketlerinin kapasitesi sınırlıdır; bazıları 144 bayt, bazıları birkaç kilobayt veri tutar. Bu nedenle etikete genellikle tüm veriyi değil, veritabanındaki kaydı temsil eden kısa bir anahtar yazılır. Yani etiket depo değil, kapı numarasıdır.</p>

<table>
  <thead>
    <tr>
      <th>Senaryo</th>
      <th>Etikete Yazılacak Veri</th>
      <th>Sunucuda Tutulacak Veri</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ürün takibi</td>
      <td><code class="language-plaintext highlighter-rouge">urun:3482</code></td>
      <td>Stok, tarihçe, bakım</td>
    </tr>
    <tr>
      <td>Müze rehberi</td>
      <td><code class="language-plaintext highlighter-rouge">eser:12</code></td>
      <td>Sesli anlatım, görsel</td>
    </tr>
    <tr>
      <td>Etkinlik girişi</td>
      <td><code class="language-plaintext highlighter-rouge">bilet:abc91</code></td>
      <td>Kullanıcı, yetki, süre</td>
    </tr>
  </tbody>
</table>

<p>Güvenlik tarafında en kritik ilke şudur: NFC’den gelen veriye asla körü körüne güvenmeyin. Etiket kopyalanabilir, değiştirilebilir veya kötü niyetli URL içerebilir. Okunan değerler sunucuda doğrulanmalı, hassas işlemler için kullanıcı oturumu ve yetki kontrolü yapılmalıdır. Matematiksel olarak düşünürsek, güvenlik sadece $veri + cihaz$ değil; $veri + cihaz + kullanıcı + sunucu doğrulaması$ birleşimidir.</p>

<p>Sonuç olarak Web NFC, mobil web uygulamalarına fiziksel dünya ile tatlı bir tokalaşma imkânı verir. Depo yönetimi, akıllı kartvizitler, müze deneyimleri, eğitim materyalleri ve hızlı yapılandırma ekranları için oldukça kullanışlıdır. Yeter ki tarayıcı desteğini kontrol edin, kullanıcı iznini saygıyla isteyin ve NFC etiketlerini minik ama güçlü anahtarlar gibi tasarlayın.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="JavaScript" /><category term="NFC" /><category term="Web NFC" /><category term="Mobil Web" /><summary type="html"><![CDATA[Telefonunuzu bir etikete yaklaştırıp kapıyı açmak, Wi-Fi bilgisini almak ya da bir ürünün bakım geçmişini okumak kulağa biraz sihir gibi gelir; ama aslında sahnede NFC ve JavaScript vardır. Modern Android tarayıcılarında Web NFC API sayesinde web uygulamaları, yakın alan iletişimi sensörleriyle veri okuyup yazabilir. Yani bazen bir buton, bazen de 3 cm mesafe bütün deneyimi değiştirir.]]></summary></entry><entry><title type="html">PHP ve Regex ile Metin Madenciliği: Kalıpları Yakala, İçeriği Otomatik Üret</title><link href="https://sonsuzus.github.io/posts/php-ve-regex-ile-metin-madenciligi-kaliplari-yakala-icerigi-otomatik-uret/" rel="alternate" type="text/html" title="PHP ve Regex ile Metin Madenciliği: Kalıpları Yakala, İçeriği Otomatik Üret" /><published>2026-07-12T00:00:00+00:00</published><updated>2026-07-12T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/php-ve-regex-ile-metin-madenciligi-kaliplari-yakala-icerigi-otomatik-uret</id><content type="html" xml:base="https://sonsuzus.github.io/posts/php-ve-regex-ile-metin-madenciligi-kaliplari-yakala-icerigi-otomatik-uret/"><![CDATA[<p>Sunucu tarafında çalışan küçük bir PHP betiği, doğru düzenli ifadelerle birleştiğinde devasa log dosyalarını, kullanıcı yorumlarını, haber metinlerini veya HTML parçalarını akıllı bir içerik fabrikasına çevirebilir. Regex, metnin içinde saklanan düzeni bulma sanatıdır; PHP ise bu sanatı otomasyona bağlayan pratik mutfaktır.
``</p>

<p>Düzenli ifadeleri bir tür metin mikroskobu gibi düşünebiliriz. Normal arama işlemi sadece birebir kelime bulurken, regex belirli bir şekle uyan metinleri yakalar. Örneğin e-posta adresleri farklı kullanıcı adlarına ve alan adlarına sahip olabilir; ama çoğu benzer bir forma uyar: kullanıcı, <code class="language-plaintext highlighter-rouge">@</code>, alan adı ve uzantı. Bu yüzden regex, tek tek kelime değil, kalıp arar.</p>

<p>Teorik olarak bir regex deseni, karakter kümeleri ve tekrar kurallarıyla tanımlanır. Basitçe şöyle düşünebiliriz: bir metin $T$, bir desen $P$ ile taranır ve eşleşme fonksiyonu $M(T, P)$ bize bulunan parçaları döndürür. Eğer amaç filtreleme ise sonuç doğru/yanlış olabilir; eğer amaç içerik üretimi ise bulunan parçalar yeni bir yapıya dönüştürülür.</p>

<table>
  <thead>
    <tr>
      <th>İhtiyaç</th>
      <th>Regex Yaklaşımı</th>
      <th>PHP Fonksiyonu</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Metinde kalıp var mı?</td>
      <td>Deseni test et</td>
      <td><code class="language-plaintext highlighter-rouge">preg_match</code></td>
    </tr>
    <tr>
      <td>Tüm eşleşmeleri bul</td>
      <td>Global yakalama</td>
      <td><code class="language-plaintext highlighter-rouge">preg_match_all</code></td>
    </tr>
    <tr>
      <td>Zararlı ifadeleri sil</td>
      <td>Eşleşeni değiştir</td>
      <td><code class="language-plaintext highlighter-rouge">preg_replace</code></td>
    </tr>
    <tr>
      <td>Metni parçalara böl</td>
      <td>Ayraç deseni kullan</td>
      <td><code class="language-plaintext highlighter-rouge">preg_split</code></td>
    </tr>
  </tbody>
</table>

<p>PHP tarafında regex işlemleri çoğunlukla PCRE motoru ile yapılır. Desenler genellikle <code class="language-plaintext highlighter-rouge">/.../</code> sınırlandırıcıları arasına yazılır. Sona eklenen <code class="language-plaintext highlighter-rouge">i</code>, büyük-küçük harf duyarsızlığı sağlar. Örneğin <code class="language-plaintext highlighter-rouge">/php/i</code>, hem <code class="language-plaintext highlighter-rouge">PHP</code> hem <code class="language-plaintext highlighter-rouge">php</code> hem de <code class="language-plaintext highlighter-rouge">Php</code> ifadelerini yakalayabilir.</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="nv">$text</span> <span class="o">=</span> <span class="s1">'İletişim: destek@example.com veya satis@site.com.tr'</span><span class="p">;</span>
<span class="nv">$pattern</span> <span class="o">=</span> <span class="s1">'/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i'</span><span class="p">;</span>

<span class="nb">preg_match_all</span><span class="p">(</span><span class="nv">$pattern</span><span class="p">,</span> <span class="nv">$text</span><span class="p">,</span> <span class="nv">$matches</span><span class="p">);</span>

<span class="k">foreach</span> <span class="p">(</span><span class="nv">$matches</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">as</span> <span class="nv">$email</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">echo</span> <span class="nv">$email</span> <span class="mf">.</span> <span class="kc">PHP_EOL</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu kodun yaptığı iş basit ama güçlüdür: metin içindeki e-posta biçimine benzeyen tüm parçaları toplar. <code class="language-plaintext highlighter-rouge">\b</code> kelime sınırını, <code class="language-plaintext highlighter-rouge">[A-Z0-9._%+-]+</code> kullanıcı adını, <code class="language-plaintext highlighter-rouge">@</code> zorunlu karakteri, devamındaki bölüm ise alan adını temsil eder. Buradaki <code class="language-plaintext highlighter-rouge">+</code> operatörü en az bir tekrar anlamına gelir. Yani matematiksel olarak <code class="language-plaintext highlighter-rouge">x+</code>, $x$ karakterinin $n \ge 1$ kez tekrar etmesi demektir.</p>

<p>Regex öğrenirken en kritik konu açgözlülük davranışıdır. <code class="language-plaintext highlighter-rouge">.*</code> mümkün olan en uzun eşleşmeyi almaya çalışır. Bu bazen çok kullanışlı, bazen de tam bir metin canavarıdır.</p>

<table>
  <thead>
    <tr>
      <th>Desen</th>
      <th>Davranış</th>
      <th>Örnek Sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">&lt;h2&gt;.*&lt;/h2&gt;</code></td>
      <td>Açgözlü</td>
      <td>İlk <code class="language-plaintext highlighter-rouge">&lt;h2&gt;</code>den son <code class="language-plaintext highlighter-rouge">&lt;/h2&gt;</code>ye kadar alabilir</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">&lt;h2&gt;.*?&lt;/h2&gt;</code></td>
      <td>Tembel</td>
      <td>En yakın <code class="language-plaintext highlighter-rouge">&lt;/h2&gt;</code>de durur</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">&lt;h2&gt;(.*?)&lt;/h2&gt;</code></td>
      <td>Yakalama gruplu</td>
      <td>Sadece başlık içeriği ayrıca alınabilir</td>
    </tr>
  </tbody>
</table>

<p>Şimdi küçük bir otomatik içerik çıkarıcı yazalım. Diyelim ki elimizde ham HTML benzeri bir metin var ve içindeki başlıkları listeleyerek mini bir özet üretmek istiyoruz.</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="nv">$html</span> <span class="o">=</span> <span class="s1">'&lt;h2&gt;Regex Nedir?&lt;/h2&gt;&lt;p&gt;Kalıp arama tekniğidir.&lt;/p&gt;&lt;h2&gt;PHP ile Kullanımı&lt;/h2&gt;'</span><span class="p">;</span>
<span class="nv">$pattern</span> <span class="o">=</span> <span class="s1">'/&lt;h2&gt;(.*?)&lt;\/h2&gt;/i'</span><span class="p">;</span>

<span class="nb">preg_match_all</span><span class="p">(</span><span class="nv">$pattern</span><span class="p">,</span> <span class="nv">$html</span><span class="p">,</span> <span class="nv">$matches</span><span class="p">);</span>

<span class="nv">$summary</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$matches</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">as</span> <span class="nv">$title</span><span class="p">)</span> <span class="p">{</span>
    <span class="nv">$summary</span><span class="p">[]</span> <span class="o">=</span> <span class="s1">'- '</span> <span class="mf">.</span> <span class="nb">trim</span><span class="p">(</span><span class="nb">strip_tags</span><span class="p">(</span><span class="nv">$title</span><span class="p">));</span>
<span class="p">}</span>

<span class="k">echo</span> <span class="nb">implode</span><span class="p">(</span><span class="kc">PHP_EOL</span><span class="p">,</span> <span class="nv">$summary</span><span class="p">);</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">(.*?)</code> kısmı yakalama grubudur. <code class="language-plaintext highlighter-rouge">preg_match_all</code> sonucunda <code class="language-plaintext highlighter-rouge">$matches[0]</code> tam eşleşmeleri, <code class="language-plaintext highlighter-rouge">$matches[1]</code> ise parantez içindeki özel bölümü verir. Böylece etiketleri değil, sadece başlık içeriğini kullanarak otomatik özet çıkarabiliriz.</p>

<p>Filtreleme tarafında ise <code class="language-plaintext highlighter-rouge">preg_replace</code> oldukça pratiktir. Örneğin yorumlardan telefon numarası gibi hassas verileri maskeleyebilirsiniz.</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
<span class="nv">$comment</span> <span class="o">=</span> <span class="s1">'Beni 0555 123 45 67 numarasından ara.'</span><span class="p">;</span>
<span class="nv">$clean</span> <span class="o">=</span> <span class="nb">preg_replace</span><span class="p">(</span><span class="s1">'/\b0\d{3}\s\d{3}\s\d{2}\s\d{2}\b/'</span><span class="p">,</span> <span class="s1">'[telefon gizlendi]'</span><span class="p">,</span> <span class="nv">$comment</span><span class="p">);</span>

<span class="k">echo</span> <span class="nv">$clean</span><span class="p">;</span>
</code></pre></div></div>

<p>Bu yaklaşım özellikle moderasyon sistemlerinde, log temizleme işlemlerinde ve veri anonimleştirmede işe yarar. Yine de regex her sorunun çekici değildir. HTML ayrıştırma için karmaşık yapılarda DOMDocument daha güvenlidir; parola doğrulamada regex yardımcıdır ama tek başına güvenlik politikası değildir.</p>

<p>Sonuç olarak PHP ve regex ikilisi, metin yığınları içinde düzen arayan geliştiriciler için hızlı, ekonomik ve güçlü bir araç setidir. Mantığı kavradığınızda, bir log satırından hata kodu çekmek de, makalelerden otomatik etiket üretmek de aynı temel fikre dayanır: kalıbı tanımla, eşleşmeyi yakala, sonucu anlamlı bir çıktıya dönüştür.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="php" /><category term="regex" /><category term="metin-isleme" /><summary type="html"><![CDATA[Sunucu tarafında çalışan küçük bir PHP betiği, doğru düzenli ifadelerle birleştiğinde devasa log dosyalarını, kullanıcı yorumlarını, haber metinlerini veya HTML parçalarını akıllı bir içerik fabrikasına çevirebilir. Regex, metnin içinde saklanan düzeni bulma sanatıdır; PHP ise bu sanatı otomasyona bağlayan pratik mutfaktır.]]></summary></entry><entry><title type="html">Python ile Olasılık Dağılımları: Yazı-Turadan Monty Hall’a Simülasyonlu İstatistik</title><link href="https://sonsuzus.github.io/posts/python-ile-olasilik-dagilimlari-yazi-turadan-monty-halla-simulasyonlu-istatistik/" rel="alternate" type="text/html" title="Python ile Olasılık Dağılımları: Yazı-Turadan Monty Hall’a Simülasyonlu İstatistik" /><published>2026-07-12T00:00:00+00:00</published><updated>2026-07-12T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/python-ile-olasilik-dagilimlari-yazi-turadan-monty-halla-simulasyonlu-istatistik</id><content type="html" xml:base="https://sonsuzus.github.io/posts/python-ile-olasilik-dagilimlari-yazi-turadan-monty-halla-simulasyonlu-istatistik/"><![CDATA[<p>Olasılık teorisi ilk bakışta zarlar, paralar ve renkli toplarla oynanan masum bir oyun gibi görünür; fakat arka planda belirsizliği ölçmeye yarayan güçlü bir matematik dili vardır. Python ise bu dili deney masasına yatırmak için harika bir laboratuvardır. Yazı-tura simülasyonlarıyla büyük sayılar yasasını gözlemleyebilir, koşullu olasılık paradokslarıyla sezgilerimizin nasıl tökezlediğini görebiliriz.
``</p>

<h2 id="olasılık-dağılımı-nedir">Olasılık dağılımı nedir?</h2>

<p>Bir rassal değişkenin alabileceği değerleri ve bu değerlerin gerçekleşme olasılıklarını tarif eden yapıya <strong>olasılık dağılımı</strong> denir. Örneğin adil bir para için sonuç kümesi $S={Yazı, Tura}$ ve her sonuç için olasılık $P(Yazı)=P(Tura)=0.5$ olur.</p>

<p>Eğer $X$, 10 atışta gelen yazı sayısını temsil ederse, $X$ artık binom dağılımına uyar:</p>

\[P(X=k)=\binom{n}{k}p^k(1-p)^{n-k}\]

<p>Burada $n$ deneme sayısı, $k$ başarı sayısı, $p$ ise tek denemedeki başarı olasılığıdır. Para adilse $p=0.5$.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Anlamı</th>
      <th>Python’da karşılığı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Deney</td>
      <td>Tekrarlanabilir süreç</td>
      <td>Döngü, fonksiyon</td>
    </tr>
    <tr>
      <td>Olay</td>
      <td>İstenen sonuç kümesi</td>
      <td>Koşul ifadesi</td>
    </tr>
    <tr>
      <td>Olasılık</td>
      <td>Olayın gerçekleşme oranı</td>
      <td>Başarı / toplam</td>
    </tr>
    <tr>
      <td>Dağılım</td>
      <td>Olasılıkların deseni</td>
      <td>Liste, sözlük, NumPy dizisi</td>
    </tr>
  </tbody>
</table>

<h2 id="yazı-tura-simülasyonu">Yazı-tura simülasyonu</h2>

<p>Teorik olarak adil parada yazı oranı $0.5$ olmalıdır. Ama 10 atışta 8 yazı gelmesi şaşırtıcı değildir. Deneme sayısı büyüdükçe oran teorik değere yaklaşır. Buna <strong>büyük sayılar yasası</strong> denir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">random</span>

<span class="k">def</span> <span class="nf">coin_flip_simulation</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="n">heads</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">ratios</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
        <span class="n">flip</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="nf">choice</span><span class="p">([</span><span class="sh">'</span><span class="s">Yazı</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">Tura</span><span class="sh">'</span><span class="p">])</span>
        <span class="k">if</span> <span class="n">flip</span> <span class="o">==</span> <span class="sh">'</span><span class="s">Yazı</span><span class="sh">'</span><span class="p">:</span>
            <span class="n">heads</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="n">ratios</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">heads</span> <span class="o">/</span> <span class="n">i</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">heads</span><span class="p">,</span> <span class="n">ratios</span>

<span class="n">heads</span><span class="p">,</span> <span class="n">ratios</span> <span class="o">=</span> <span class="nf">coin_flip_simulation</span><span class="p">(</span><span class="mi">10000</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">Yazı sayısı:</span><span class="sh">'</span><span class="p">,</span> <span class="n">heads</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">Son oran:</span><span class="sh">'</span><span class="p">,</span> <span class="n">ratios</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</code></pre></div></div>

<p>Bu kodda her atış bağımsızdır; yani önceki sonucun sonraki sonucu etkilemediğini varsayarız. İşte bu nokta önemlidir: Art arda 5 kez tura gelmesi, bir sonraki atışta yazı olasılığını artırmaz. Hâlâ $P(Yazı)=0.5$.</p>

<h2 id="dağılımı-sayarak-görmek">Dağılımı sayarak görmek</h2>

<p>10 kez para atıp kaç yazı geldiğini bir kez hesaplamak yerine, bu deneyi binlerce kez tekrar edebiliriz. Böylece deneysel binom dağılımını elde ederiz.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">collections</span> <span class="kn">import</span> <span class="n">Counter</span>
<span class="kn">import</span> <span class="n">random</span>

<span class="k">def</span> <span class="nf">count_heads_in_trial</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="k">return</span> <span class="nf">sum</span><span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="nf">choice</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>

<span class="k">def</span> <span class="nf">binomial_experiment</span><span class="p">(</span><span class="n">trials</span><span class="p">,</span> <span class="n">flips_per_trial</span><span class="p">):</span>
    <span class="n">results</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">trials</span><span class="p">):</span>
        <span class="n">results</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="nf">count_heads_in_trial</span><span class="p">(</span><span class="n">flips_per_trial</span><span class="p">))</span>
    <span class="k">return</span> <span class="nc">Counter</span><span class="p">(</span><span class="n">results</span><span class="p">)</span>

<span class="n">dist</span> <span class="o">=</span> <span class="nf">binomial_experiment</span><span class="p">(</span><span class="mi">20000</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>
<span class="k">for</span> <span class="n">heads_count</span> <span class="ow">in</span> <span class="nf">sorted</span><span class="p">(</span><span class="n">dist</span><span class="p">):</span>
    <span class="nf">print</span><span class="p">(</span><span class="n">heads_count</span><span class="p">,</span> <span class="n">dist</span><span class="p">[</span><span class="n">heads_count</span><span class="p">]</span> <span class="o">/</span> <span class="mi">20000</span><span class="p">)</span>
</code></pre></div></div>

<p>Burada 0’dan 10’a kadar yazı sayılarının göreli frekanslarını görürüz. Teorik olarak en yüksek değerler 5 civarında toplanır; çünkü 10 atışta 5 yazı gelme olasılığı uç değerlere göre daha fazladır.</p>

<table>
  <thead>
    <tr>
      <th>Yazı sayısı</th>
      <th>Yorum</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>0 veya 10</td>
      <td>Çok nadir, uç durum</td>
    </tr>
    <tr>
      <td>4, 5, 6</td>
      <td>En olası bölge</td>
    </tr>
    <tr>
      <td>1, 2, 8, 9</td>
      <td>Mümkün ama daha seyrek</td>
    </tr>
  </tbody>
</table>

<h2 id="koşullu-olasılık-monty-hall-paradoksu">Koşullu olasılık: Monty Hall paradoksu</h2>

<p>Koşullu olasılık, bir olayın gerçekleştiğini bildiğimizde başka bir olayın olasılığını günceller. Formül şöyledir:</p>

\[P(A|B)=\frac{P(A\cap B)}{P(B)}\]

<p>Monty Hall probleminde 3 kapı vardır. Birinde araba, ikisinde keçi bulunur. Oyuncu bir kapı seçer. Sunucu, arabanın olmadığı bir kapıyı açar. Oyuncuya seçim değiştirme hakkı verilir. Sezgisel cevap “fark etmez, olasılık yarı yarıya” olabilir; ama doğru strateji değiştirmektir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">random</span>

<span class="k">def</span> <span class="nf">monty_hall</span><span class="p">(</span><span class="n">change</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">trials</span><span class="o">=</span><span class="mi">10000</span><span class="p">):</span>
    <span class="n">wins</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">doors</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>

    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">trials</span><span class="p">):</span>
        <span class="n">car</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="nf">choice</span><span class="p">(</span><span class="n">doors</span><span class="p">)</span>
        <span class="n">choice</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="nf">choice</span><span class="p">(</span><span class="n">doors</span><span class="p">)</span>

        <span class="n">possible_opens</span> <span class="o">=</span> <span class="p">[</span><span class="n">d</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">doors</span> <span class="k">if</span> <span class="n">d</span> <span class="o">!=</span> <span class="n">choice</span> <span class="ow">and</span> <span class="n">d</span> <span class="o">!=</span> <span class="n">car</span><span class="p">]</span>
        <span class="n">opened</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="nf">choice</span><span class="p">(</span><span class="n">possible_opens</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">change</span><span class="p">:</span>
            <span class="n">choice</span> <span class="o">=</span> <span class="p">[</span><span class="n">d</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">doors</span> <span class="k">if</span> <span class="n">d</span> <span class="o">!=</span> <span class="n">choice</span> <span class="ow">and</span> <span class="n">d</span> <span class="o">!=</span> <span class="n">opened</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>

        <span class="k">if</span> <span class="n">choice</span> <span class="o">==</span> <span class="n">car</span><span class="p">:</span>
            <span class="n">wins</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">return</span> <span class="n">wins</span> <span class="o">/</span> <span class="n">trials</span>

<span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">Değiştirirse:</span><span class="sh">'</span><span class="p">,</span> <span class="nf">monty_hall</span><span class="p">(</span><span class="bp">True</span><span class="p">))</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">Değiştirmezse:</span><span class="sh">'</span><span class="p">,</span> <span class="nf">monty_hall</span><span class="p">(</span><span class="bp">False</span><span class="p">))</span>
</code></pre></div></div>

<p>Sonuçlar genellikle değiştirme stratejisinin yaklaşık $\frac{2}{3}$, değiştirmeme stratejisinin ise yaklaşık $\frac{1}{3}$ kazandırdığını gösterir.</p>

<table>
  <thead>
    <tr>
      <th>Strateji</th>
      <th style="text-align: right">Kazanma olasılığı</th>
      <th>Sezgisel mi?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kapıyı değiştirme</td>
      <td style="text-align: right">$1/3$</td>
      <td>Evet</td>
    </tr>
    <tr>
      <td>Kapıyı değiştir</td>
      <td style="text-align: right">$2/3$</td>
      <td>Hayır, ama doğru</td>
    </tr>
  </tbody>
</table>

<h2 id="sonuç">Sonuç</h2>

<p>Python ile olasılık dağılımlarını modellemek, formülleri ezberlemekten daha kalıcı bir öğrenme sağlar. Simülasyonlar bize şunu öğretir: Kısa vadede rastgelelik gürültülüdür, uzun vadede ise matematik kendini belli eder. Yazı-tura örneği büyük sayılar yasasını, Monty Hall ise koşullu olasılığın sezgilerimize karşı nasıl galip geldiğini gösterir. Kısacası Python, istatistiği kuru bir konu olmaktan çıkarıp deney yapılabilir bir oyun alanına dönüştürür.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="python" /><category term="olasılık" /><category term="simülasyon" /><category term="istatistik" /><summary type="html"><![CDATA[Olasılık teorisi ilk bakışta zarlar, paralar ve renkli toplarla oynanan masum bir oyun gibi görünür; fakat arka planda belirsizliği ölçmeye yarayan güçlü bir matematik dili vardır. Python ise bu dili deney masasına yatırmak için harika bir laboratuvardır. Yazı-tura simülasyonlarıyla büyük sayılar yasasını gözlemleyebilir, koşullu olasılık paradokslarıyla sezgilerimizin nasıl tökezlediğini görebiliriz.]]></summary></entry><entry><title type="html">Go’nun Eşzamanlılık Mimarisi: Goroutine ile Hafif ve Hızlı Servisler</title><link href="https://sonsuzus.github.io/posts/gonun-eszamanlilik-mimarisi-goroutine-ile-hafif-ve-hizli-servisler/" rel="alternate" type="text/html" title="Go’nun Eşzamanlılık Mimarisi: Goroutine ile Hafif ve Hızlı Servisler" /><published>2026-07-11T00:00:00+00:00</published><updated>2026-07-11T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/gonun-eszamanlilik-mimarisi-goroutine-ile-hafif-ve-hizli-servisler</id><content type="html" xml:base="https://sonsuzus.github.io/posts/gonun-eszamanlilik-mimarisi-goroutine-ile-hafif-ve-hizli-servisler/"><![CDATA[<p>Go’da eşzamanlılık, “aynı anda çok iş yapıyormuş gibi” görünen kod yazmaktan daha fazlasıdır; dilin tasarım felsefesine gömülü bir üretkenlik süper gücüdür. Binlerce arka plan görevini, ağ isteğini, kuyruk işini veya zamanlayıcıyı klasik thread maliyetlerine boğulmadan yönetmek istiyorsanız, goroutine’ler tam olarak bu sahneye davul zurna ile girer.
``</p>

<p>Go’nun concurrency yaklaşımını anlamanın ilk adımı şu ayrımı netleştirmektir: <strong>Concurrency</strong> aynı zaman aralığında birden fazla işle ilerleyebilme yeteneğidir; <strong>parallelism</strong> ise gerçekten aynı anda, farklı CPU çekirdeklerinde çalışmaktır. Yani concurrency bir tasarım modeli, parallelism ise donanımın sunduğu fiziksel imkândır.</p>

<p>Basitçe ifade edersek:</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Anlamı</th>
      <th>Go’daki karşılığı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Concurrency</td>
      <td>İşleri bağımsız parçalara bölmek</td>
      <td>Goroutine, channel, select</td>
    </tr>
    <tr>
      <td>Parallelism</td>
      <td>İşleri aynı anda CPU’da yürütmek</td>
      <td>Çok çekirdek + scheduler</td>
    </tr>
    <tr>
      <td>Thread</td>
      <td>İşletim sistemi düzeyinde ağır yürütme birimi</td>
      <td>OS thread</td>
    </tr>
    <tr>
      <td>Goroutine</td>
      <td>Go runtime tarafından yönetilen hafif görev</td>
      <td><code class="language-plaintext highlighter-rouge">go func()</code></td>
    </tr>
  </tbody>
</table>

<p>Go runtime içinde ünlü <strong>M:P:G modeli</strong> çalışır. Burada <code class="language-plaintext highlighter-rouge">G</code> goroutine’i, <code class="language-plaintext highlighter-rouge">M</code> işletim sistemi thread’ini, <code class="language-plaintext highlighter-rouge">P</code> ise işlemci bağlamını temsil eder. Kabaca ilişkiyi şöyle düşünebiliriz: $G \rightarrow P \rightarrow M$. Eğer $N$ adet goroutine’iniz ve $P$ adet işlemci bağlamınız varsa, Go scheduler bu goroutine’leri uygun thread’lere dağıtarak verimli çalıştırır. Bu yüzden binlerce goroutine açmak çoğu senaryoda binlerce OS thread açmaktan çok daha ucuzdur.</p>

<p>Goroutine başlatmak şaşırtıcı derecede kolaydır:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="k">import</span> <span class="p">(</span>
    <span class="s">"fmt"</span>
    <span class="s">"time"</span>
<span class="p">)</span>

<span class="k">func</span> <span class="n">sendEmail</span><span class="p">(</span><span class="n">user</span> <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">time</span><span class="o">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">500</span> <span class="o">*</span> <span class="n">time</span><span class="o">.</span><span class="n">Millisecond</span><span class="p">)</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="s">"E-posta gönderildi:"</span><span class="p">,</span> <span class="n">user</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">users</span> <span class="o">:=</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">"ada"</span><span class="p">,</span> <span class="s">"linus"</span><span class="p">,</span> <span class="s">"grace"</span><span class="p">}</span>

    <span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">user</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">users</span> <span class="p">{</span>
        <span class="k">go</span> <span class="n">sendEmail</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
    <span class="p">}</span>

    <span class="n">time</span><span class="o">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">1</span> <span class="o">*</span> <span class="n">time</span><span class="o">.</span><span class="n">Second</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu örnekte her kullanıcı için ayrı bir goroutine başlatılır. <code class="language-plaintext highlighter-rouge">sendEmail</code> fonksiyonu bloklansa bile ana akış diğer işleri başlatmaya devam eder. Ancak gerçek projelerde <code class="language-plaintext highlighter-rouge">time.Sleep</code> ile beklemek pek yakışıklı değildir; bu, restoranda garsona “yemekler herhalde gelir” deyip göz kararı beklemek gibidir.</p>

<p>Daha kontrollü bir yapı için <code class="language-plaintext highlighter-rouge">channel</code> kullanırız. Channel’lar goroutine’ler arasında güvenli veri aktarımı sağlar. Go’nun meşhur sözü burada devreye girer: <strong>Belleği paylaşarak iletişim kurma; iletişim kurarak belleği paylaş.</strong></p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="k">import</span> <span class="p">(</span>
    <span class="s">"context"</span>
    <span class="s">"fmt"</span>
    <span class="s">"time"</span>
<span class="p">)</span>

<span class="k">func</span> <span class="n">worker</span><span class="p">(</span><span class="n">ctx</span> <span class="n">context</span><span class="o">.</span><span class="n">Context</span><span class="p">,</span> <span class="n">jobs</span> <span class="o">&lt;-</span><span class="k">chan</span> <span class="kt">string</span><span class="p">,</span> <span class="n">results</span> <span class="k">chan</span><span class="o">&lt;-</span> <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">for</span> <span class="p">{</span>
        <span class="k">select</span> <span class="p">{</span>
        <span class="k">case</span> <span class="o">&lt;-</span><span class="n">ctx</span><span class="o">.</span><span class="n">Done</span><span class="p">()</span><span class="o">:</span>
            <span class="k">return</span>
        <span class="k">case</span> <span class="n">job</span><span class="p">,</span> <span class="n">ok</span> <span class="o">:=</span> <span class="o">&lt;-</span><span class="n">jobs</span><span class="o">:</span>
            <span class="k">if</span> <span class="o">!</span><span class="n">ok</span> <span class="p">{</span>
                <span class="k">return</span>
            <span class="p">}</span>
            <span class="n">time</span><span class="o">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">300</span> <span class="o">*</span> <span class="n">time</span><span class="o">.</span><span class="n">Millisecond</span><span class="p">)</span>
            <span class="n">results</span> <span class="o">&lt;-</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"İş tamamlandı: %s"</span><span class="p">,</span> <span class="n">job</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">ctx</span><span class="p">,</span> <span class="n">cancel</span> <span class="o">:=</span> <span class="n">context</span><span class="o">.</span><span class="n">WithTimeout</span><span class="p">(</span><span class="n">context</span><span class="o">.</span><span class="n">Background</span><span class="p">(),</span> <span class="m">2</span><span class="o">*</span><span class="n">time</span><span class="o">.</span><span class="n">Second</span><span class="p">)</span>
    <span class="k">defer</span> <span class="n">cancel</span><span class="p">()</span>

    <span class="n">jobs</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="k">chan</span> <span class="kt">string</span><span class="p">)</span>
    <span class="n">results</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="k">chan</span> <span class="kt">string</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">i</span> <span class="o">:=</span> <span class="m">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="m">3</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span> <span class="p">{</span>
        <span class="k">go</span> <span class="n">worker</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">jobs</span><span class="p">,</span> <span class="n">results</span><span class="p">)</span>
    <span class="p">}</span>

    <span class="k">go</span> <span class="k">func</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">defer</span> <span class="nb">close</span><span class="p">(</span><span class="n">jobs</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">i</span> <span class="o">:=</span> <span class="m">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="m">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span> <span class="p">{</span>
            <span class="n">jobs</span> <span class="o">&lt;-</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Sprintf</span><span class="p">(</span><span class="s">"görev-%d"</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}()</span>

    <span class="k">for</span> <span class="n">i</span> <span class="o">:=</span> <span class="m">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="m">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span> <span class="p">{</span>
        <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="o">&lt;-</span><span class="n">results</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada üç worker goroutine’i aynı <code class="language-plaintext highlighter-rouge">jobs</code> kanalından görev alır ve sonuçları <code class="language-plaintext highlighter-rouge">results</code> kanalına gönderir. <code class="language-plaintext highlighter-rouge">context</code> ise servis kapanışı, timeout veya iptal sinyalleri için temiz bir kontrol mekanizması sunar. Bu yapı, e-posta gönderimi, görsel işleme, log toplama veya webhook tüketimi gibi arka plan servislerinde sıkça kullanılır.</p>

<p>Performans açısından bakarsak, goroutine’lerin başlangıç stack’i küçüktür ve ihtiyaç oldukça büyür. Klasik thread’lerde stack maliyeti megabaytlarla ifade edilebilirken, goroutine’lerde başlangıç maliyeti kilobayt seviyesindedir. Teorik olarak toplam bellek tüketimini şöyle düşünebiliriz: $ToplamBellek \approx n \times s$. Burada $n$ görev sayısı, $s$ ise görev başına stack maliyetidir. $s$ küçüldükçe aynı makinede daha fazla eşzamanlı iş yönetebilirsiniz.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tek thread</td>
      <td>Basit akış</td>
      <td>Bloklanınca her şey yavaşlar</td>
    </tr>
    <tr>
      <td>OS thread havuzu</td>
      <td>Paralel çalışma</td>
      <td>Daha yüksek bellek maliyeti</td>
    </tr>
    <tr>
      <td>Goroutine</td>
      <td>Hafif, hızlı, okunabilir</td>
      <td>Yanlış channel kullanımı deadlock doğurabilir</td>
    </tr>
  </tbody>
</table>

<p>Tabii goroutine açmak bedava değildir; sadece ucuzdur. Sonsuz sayıda goroutine başlatmak, mutfağa sınırsız sipariş yollayıp aşçıdan mucize beklemek gibidir. Bu nedenle worker pool, rate limit, context cancellation ve buffer’lı channel gibi tekniklerle sisteminize sınır koymalısınız.</p>

<p>Sonuç olarak Go’nun concurrency mimarisi, basit sözdizimiyle güçlü bir runtime mühendisliğini birleştirir. Goroutine’ler sayesinde arka plan servisleri hem okunabilir hem de yüksek verimli olabilir. Eğer kuyruk tüketen, API çağrılarını paralelleştiren veya binlerce bağlantıyı yöneten bir servis yazıyorsanız, Go size “thread açalım mı?” diye sormaz; zarifçe <code class="language-plaintext highlighter-rouge">go</code> anahtar kelimesini uzatır ve “hadi işi bölelim” der.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="golang" /><category term="concurrency" /><category term="goroutine" /><category term="backend" /><summary type="html"><![CDATA[Go’da eşzamanlılık, “aynı anda çok iş yapıyormuş gibi” görünen kod yazmaktan daha fazlasıdır; dilin tasarım felsefesine gömülü bir üretkenlik süper gücüdür. Binlerce arka plan görevini, ağ isteğini, kuyruk işini veya zamanlayıcıyı klasik thread maliyetlerine boğulmadan yönetmek istiyorsanız, goroutine’ler tam olarak bu sahneye davul zurna ile girer.]]></summary></entry><entry><title type="html">IDE’lerde Çoklu Dil Mimarisi: Tek Çalışma Alanında Backend, Betik ve Önyüz Senfonisi</title><link href="https://sonsuzus.github.io/posts/idelerde-coklu-dil-mimarisi-tek-calisma-alaninda-backend-betik-ve-onyuz-senfonisi/" rel="alternate" type="text/html" title="IDE’lerde Çoklu Dil Mimarisi: Tek Çalışma Alanında Backend, Betik ve Önyüz Senfonisi" /><published>2026-07-11T00:00:00+00:00</published><updated>2026-07-11T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/idelerde-coklu-dil-mimarisi-tek-calisma-alaninda-backend-betik-ve-onyuz-senfonisi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/idelerde-coklu-dil-mimarisi-tek-calisma-alaninda-backend-betik-ve-onyuz-senfonisi/"><![CDATA[<p>Modern bir IDE artık sadece renkli parantez gösteren bir metin editörü değil; adeta küçük bir yazılım işletim sistemi. Aynı çalışma alanında TypeScript ile önyüz geliştirirken, Python betikleriyle otomasyon çalıştırabilir, Go ya da Java servislerini debug edebilir ve tüm bu parçaları tek bir proje akışı gibi yönetebilirsiniz. Çoklu dil mimarisi tam da burada devreye girer: IDE, farklı dillerin araçlarını ortak bir orkestrada buluşturur.
``
Bu mimarinin kalbinde şu fikir vardır: IDE her dili doğrudan kendi içinde yeniden icat etmez; bunun yerine dil sunucuları, hata ayıklama adaptörleri, görev çalıştırıcıları ve eklentilerle konuşur. Yani editör kısmı kullanıcı arayüzüdür, zeka ise çoğunlukla arka plandaki servislerden gelir. Bu ayrım sayesinde aynı ekranda React bileşeni yazarken, arka planda veritabanı migrasyonu hazırlayan bir betik de çalışabilir.</p>

<p>Teorik olarak sistemi şu denklemle düşünebiliriz: $IDE = Editör + LSP + DAP + TaskRunner + Eklenti$. Burada LSP, Language Server Protocol yani dil sunucusu protokolüdür. Kod tamamlama, sembole gitme, hata işaretleme gibi özellikleri sağlar. DAP, Debug Adapter Protocol ile hata ayıklama dünyasını standartlaştırır. TaskRunner ise derleme, test, lint ve deploy gibi komutları yönetir.</p>

<table>
  <thead>
    <tr>
      <th>Bileşen</th>
      <th>Görevi</th>
      <th>Örnek kullanım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>LSP</td>
      <td>Dil zekası sağlar</td>
      <td>TypeScript hatalarını anlık gösterme</td>
    </tr>
    <tr>
      <td>DAP</td>
      <td>Debug sürecini soyutlar</td>
      <td>Python betiğinde breakpoint kullanma</td>
    </tr>
    <tr>
      <td>Task Runner</td>
      <td>Komutları otomatik çalıştırır</td>
      <td>npm test ve pytest zinciri</td>
    </tr>
    <tr>
      <td>Eklenti Sistemi</td>
      <td>IDE davranışını genişletir</td>
      <td>Docker, Git, Kubernetes paneli</td>
    </tr>
  </tbody>
</table>

<p>Çoklu dil çalışma alanında önemli kavramlardan biri bağımlılık grafiğidir. Diyelim ki önyüz projesi API tiplerini otomatik üretilen bir dosyadan alıyor. Bu durumda $frontend \rightarrow generatedTypes \rightarrow backendSchema$ şeklinde bir ilişki oluşur. IDE bu ilişkiyi görevlerle temsil ederse, geliştirici tek tuşla önce şemayı güncelleyip sonra önyüzü başlatabilir.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">type</span> <span class="nx">Task</span> <span class="o">=</span> <span class="p">{</span> <span class="na">name</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span> <span class="nl">run</span><span class="p">:</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nb">Promise</span><span class="o">&lt;</span><span class="k">void</span><span class="o">&gt;</span> <span class="p">};</span>

<span class="kd">const</span> <span class="nx">tasks</span><span class="p">:</span> <span class="nx">Task</span><span class="p">[]</span> <span class="o">=</span> <span class="p">[</span>
  <span class="p">{</span> <span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">api:generate</span><span class="dl">'</span><span class="p">,</span> <span class="na">run</span><span class="p">:</span> <span class="k">async </span><span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">OpenAPI tipleri üretildi</span><span class="dl">'</span><span class="p">)</span> <span class="p">},</span>
  <span class="p">{</span> <span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">frontend:lint</span><span class="dl">'</span><span class="p">,</span> <span class="na">run</span><span class="p">:</span> <span class="k">async </span><span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Önyüz kontrol edildi</span><span class="dl">'</span><span class="p">)</span> <span class="p">},</span>
  <span class="p">{</span> <span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">frontend:dev</span><span class="dl">'</span><span class="p">,</span> <span class="na">run</span><span class="p">:</span> <span class="k">async </span><span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Vite geliştirme sunucusu açıldı</span><span class="dl">'</span><span class="p">)</span> <span class="p">}</span>
<span class="p">];</span>

<span class="k">async</span> <span class="kd">function</span> <span class="nf">runPipeline</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">for </span><span class="p">(</span><span class="kd">const</span> <span class="nx">task</span> <span class="k">of</span> <span class="nx">tasks</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Çalışıyor:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">task</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
    <span class="k">await</span> <span class="nx">task</span><span class="p">.</span><span class="nf">run</span><span class="p">();</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="nf">runPipeline</span><span class="p">();</span>
</code></pre></div></div>

<p>Bu kod basit bir görev hattını temsil eder. Gerçek IDE içinde bu yapı çoğu zaman launch, tasks veya workspace ayarlarıyla tanımlanır. Ama mantık aynıdır: görevler sıraya alınır, çıktılar terminalde toplanır, hata olursa zincir durdurulur ya da kullanıcı uyarılır.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Risk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tek dil, tek proje</td>
      <td>Basit kurulum</td>
      <td>Büyük sistemlerde yetersiz kalır</td>
    </tr>
    <tr>
      <td>Çoklu dil, ayrı klasörler</td>
      <td>Sorumluluklar netleşir</td>
      <td>Araçlar kopuk çalışabilir</td>
    </tr>
    <tr>
      <td>Çoklu dil, tek workspace</td>
      <td>Entegre deneyim</td>
      <td>Doğru yapılandırma ister</td>
    </tr>
  </tbody>
</table>

<p>Gelişmiş IDE’lerde bu entegrasyonun eğlenceli kısmı otomasyondur. Örneğin dosya kaydedildiğinde formatter çalışır, testler tetiklenir, tip dosyaları yenilenir ve önyüz sıcak yenileme ile güncellenir. Kullanıcı sadece kod yazar; IDE sahne arkasında küçük bir robot ordusu gibi çalışır. Ancak bu robot ordusunun kontrolden çıkmaması için net kurallar gerekir: görev adları anlamlı olmalı, ortam değişkenleri belgelenmeli, her dilin bağımlılık yönetimi izole edilmelidir.</p>

<p>Pratikte iyi bir çoklu dil IDE mimarisi için üç öneri öne çıkar. Birincisi, her teknolojinin kendi doğal aracını kullanın; Python için venv, Node için pnpm veya npm, Java için Maven gibi. İkincisi, ortak akışları IDE görevlerine bağlayın. Üçüncüsü, debug yapılandırmalarını ekip içinde paylaşın. Böylece yeni gelen geliştirici projeyi klonladığında sadece kodu değil, çalışma ritüelini de devralır.</p>

<p>Sonuç olarak çoklu dil mimarisi, IDE’yi pasif bir editörden aktif bir geliştirme merkezine dönüştürür. Arka plandaki otomasyon betikleri, önyüz projeleri ve servisler aynı sahnede buluştuğunda üretkenlik artar. Doğru kurgulanmış bir workspace, geliştiriciye şu hissi verir: Farklı diller konuşan bir ekip var, ama hepsi aynı orkestrada çalıyor.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="IDE" /><category term="LSP" /><category term="çoklu dil mimarisi" /><category term="otomasyon" /><category term="frontend" /><summary type="html"><![CDATA[Modern bir IDE artık sadece renkli parantez gösteren bir metin editörü değil; adeta küçük bir yazılım işletim sistemi. Aynı çalışma alanında TypeScript ile önyüz geliştirirken, Python betikleriyle otomasyon çalıştırabilir, Go ya da Java servislerini debug edebilir ve tüm bu parçaları tek bir proje akışı gibi yönetebilirsiniz. Çoklu dil mimarisi tam da burada devreye girer: IDE, farklı dillerin araçlarını ortak bir orkestrada buluşturur.]]></summary></entry><entry><title type="html">JavaScript ile Tarayıcı Üzerinde Sosyolojik Deneyler</title><link href="https://sonsuzus.github.io/posts/javascript-ile-tarayici-uzerinde-sosyolojik-deneyler/" rel="alternate" type="text/html" title="JavaScript ile Tarayıcı Üzerinde Sosyolojik Deneyler" /><published>2026-07-11T00:00:00+00:00</published><updated>2026-07-11T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/javascript-ile-tarayici-uzerinde-sosyolojik-deneyler</id><content type="html" xml:base="https://sonsuzus.github.io/posts/javascript-ile-tarayici-uzerinde-sosyolojik-deneyler/"><![CDATA[<p>Tarayıcı, sadece butonlara tıkladığımız bir ekran değil; aynı zamanda küçük ölçekli davranış deneyleri yapabileceğimiz harika bir laboratuvardır. JavaScript sayesinde kullanıcıların seçimlerini, tepki sürelerini, dikkat kaymalarını ve karar örüntülerini analiz eden etkileşimli psikoloji ya da zeka testleri tasarlayabiliriz. Elbette burada amaç “insanı çözmek” değil; etik sınırlar içinde, anonim ve öğretici deneyimler üretmektir.
``</p>

<p>Bu tür uygulamaların temelinde üç kavram vardır: <strong>uyaran</strong>, <strong>tepki</strong> ve <strong>ölçüm</strong>. Uyaran; ekranda gösterilen soru, görsel, renk ya da görevdir. Tepki; kullanıcının tıklaması, yazması, sürüklemesi veya beklemesidir. Ölçüm ise bu tepkinin zamana, doğruluğa veya tutarlılığa göre sayısallaştırılmasıdır. Basit bir modelle kullanıcı davranış skoru şöyle düşünülebilir: $S = w_1 x_1 + w_2 x_2 + w_3 x_3$. Burada $x$ değerleri davranış ölçümlerini, $w$ değerleri ise bu ölçümlerin ağırlıklarını temsil eder.</p>

<p>Daha genel biçimde, bir test puanını şu şekilde ifade edebiliriz:</p>

\[S = \sum_{i=1}^{n} w_i x_i\]

<p>Bu formül bize şunu söyler: Her cevap aynı önemde olmak zorunda değildir. Örneğin bir hafıza testinde doğru cevap kadar cevap verme süresi de anlamlı olabilir.</p>

<table>
  <thead>
    <tr>
      <th>Ölçüm Türü</th>
      <th>Ne Anlatır?</th>
      <th>JavaScript ile Nasıl Yakalanır?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tepki süresi</td>
      <td>Karar hızı</td>
      <td><code class="language-plaintext highlighter-rouge">performance.now()</code></td>
    </tr>
    <tr>
      <td>Tıklama seçimi</td>
      <td>Tercih yönelimi</td>
      <td><code class="language-plaintext highlighter-rouge">click</code> event</td>
    </tr>
    <tr>
      <td>Hata sayısı</td>
      <td>Dikkat veya bilgi düzeyi</td>
      <td>Sayaç değişkenleri</td>
    </tr>
    <tr>
      <td>Sıralama davranışı</td>
      <td>Öncelik algısı</td>
      <td>Drag &amp; drop olayları</td>
    </tr>
  </tbody>
</table>

<p>Dinamik DOM manipülasyonu burada sahnenin ışıkçısı gibidir. Kullanıcı bir soruya cevap verdiğinde yeni soru gösterilir, renkler değişir, sonuç ekranı oluşturulur veya zorluk seviyesi artırılır. Böylece sayfa yenilenmeden akıcı bir deney tasarlanır.</p>

<p>Aşağıdaki örnek, basit bir dikkat testi mantığını gösterir. Kullanıcıdan ekranda beliren hedef renge mümkün olduğunca hızlı tıklaması istenir:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nf">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">#app</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">colors</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">red</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">blue</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">green</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">purple</span><span class="dl">'</span><span class="p">];</span>
<span class="kd">let</span> <span class="nx">startTime</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">results</span> <span class="o">=</span> <span class="p">[];</span>

<span class="kd">function</span> <span class="nf">newRound</span><span class="p">()</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">target</span> <span class="o">=</span> <span class="nx">colors</span><span class="p">[</span><span class="nb">Math</span><span class="p">.</span><span class="nf">floor</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nf">random</span><span class="p">()</span> <span class="o">*</span> <span class="nx">colors</span><span class="p">.</span><span class="nx">length</span><span class="p">)];</span>
  <span class="nx">startTime</span> <span class="o">=</span> <span class="nx">performance</span><span class="p">.</span><span class="nf">now</span><span class="p">();</span>

  <span class="nx">app</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="s2">`
    &lt;p&gt;Hedef renk: &lt;strong&gt;</span><span class="p">${</span><span class="nx">target</span><span class="p">}</span><span class="s2">&lt;/strong&gt;&lt;/p&gt;
    &lt;div class='grid'&gt;
      </span><span class="p">${</span><span class="nx">colors</span><span class="p">.</span><span class="nf">map</span><span class="p">(</span><span class="nx">color</span> <span class="o">=&gt;</span> <span class="s2">`&lt;button class='box' data-color='</span><span class="p">${</span><span class="nx">color</span><span class="p">}</span><span class="s2">' style='background:</span><span class="p">${</span><span class="nx">color</span><span class="p">}</span><span class="s2">'&gt;&lt;/button&gt;`</span><span class="p">).</span><span class="nf">join</span><span class="p">(</span><span class="dl">''</span><span class="p">)}</span><span class="s2">
    &lt;/div&gt;
  `</span><span class="p">;</span>

  <span class="nb">document</span><span class="p">.</span><span class="nf">querySelectorAll</span><span class="p">(</span><span class="dl">'</span><span class="s1">.box</span><span class="dl">'</span><span class="p">).</span><span class="nf">forEach</span><span class="p">(</span><span class="nx">button</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">button</span><span class="p">.</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="kd">const</span> <span class="nx">reaction</span> <span class="o">=</span> <span class="nx">performance</span><span class="p">.</span><span class="nf">now</span><span class="p">()</span> <span class="o">-</span> <span class="nx">startTime</span><span class="p">;</span>
      <span class="kd">const</span> <span class="nx">correct</span> <span class="o">=</span> <span class="nx">button</span><span class="p">.</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">color</span> <span class="o">===</span> <span class="nx">target</span><span class="p">;</span>
      <span class="nx">results</span><span class="p">.</span><span class="nf">push</span><span class="p">({</span> <span class="nx">reaction</span><span class="p">,</span> <span class="nx">correct</span> <span class="p">});</span>
      <span class="nf">showFeedback</span><span class="p">(</span><span class="nx">correct</span><span class="p">,</span> <span class="nx">reaction</span><span class="p">);</span>
    <span class="p">});</span>
  <span class="p">});</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nf">showFeedback</span><span class="p">(</span><span class="nx">correct</span><span class="p">,</span> <span class="nx">reaction</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">app</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="s2">`
    &lt;p&gt;</span><span class="p">${</span><span class="nx">correct</span> <span class="p">?</span> <span class="dl">'</span><span class="s1">Doğru!</span><span class="dl">'</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">Yanlış!</span><span class="dl">'</span><span class="p">}</span><span class="s2">&lt;/p&gt;
    &lt;p&gt;Tepki süresi: </span><span class="p">${</span><span class="nb">Math</span><span class="p">.</span><span class="nf">round</span><span class="p">(</span><span class="nx">reaction</span><span class="p">)}</span><span class="s2"> ms&lt;/p&gt;
    &lt;button id='next'&gt;Yeni Tur&lt;/button&gt;
  `</span><span class="p">;</span>
  <span class="nb">document</span><span class="p">.</span><span class="nf">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">#next</span><span class="dl">'</span><span class="p">).</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="nx">newRound</span><span class="p">);</span>
<span class="p">}</span>

<span class="nf">newRound</span><span class="p">();</span>
</code></pre></div></div>

<p>Bu kodda <code class="language-plaintext highlighter-rouge">performance.now()</code> milisaniye hassasiyetinde zaman ölçer. Kullanıcının doğru renge tıklayıp tıklamadığı <code class="language-plaintext highlighter-rouge">dataset</code> üzerinden kontrol edilir. DOM, her turda yeniden çizilerek testin akışı yönetilir.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Risk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sabit sorular</td>
      <td>Kolay analiz</td>
      <td>Ezberlenebilir</td>
    </tr>
    <tr>
      <td>Rastgele uyaran</td>
      <td>Daha doğal veri</td>
      <td>Karşılaştırma zorlaşır</td>
    </tr>
    <tr>
      <td>Zaman ölçümü</td>
      <td>Hızlı içgörü</td>
      <td>Cihaz farklarından etkilenir</td>
    </tr>
    <tr>
      <td>Kişiselleştirme</td>
      <td>Etkileşim artar</td>
      <td>Gizlilik sorumluluğu doğar</td>
    </tr>
  </tbody>
</table>

<p>Sosyolojik veya psikolojik deneylerde en kritik konu <strong>etik tasarım</strong>dır. Kullanıcıdan açık rıza alınmalı, veriler anonimleştirilmeli ve sonuçlar kesin tanı gibi sunulmamalıdır. “Zekan 142 çıktı” demek yerine “Bu mini testte hızlı örüntü tanıma eğilimi gösterdin” demek çok daha sağlıklıdır.</p>

<p>Sonuç ekranı da davranış analizi kadar önemlidir. Kullanıcıya grafikler, ortalama tepki süresi ve doğru cevap oranı gösterilebilir. Örneğin doğruluk oranı $D = doğru / toplam$ formülüyle hesaplanır. Bu basit oran, anlaşılır bir geri bildirim üretir.</p>

<p>JavaScript ile tarayıcı üzerinde böyle deneyler tasarlamak; DOM, event yönetimi, veri modelleme ve kullanıcı deneyimi bilgisini aynı projede buluşturur. Küçük başlayın: üç soru, bir sayaç ve basit bir skor ekranı yeterli. Sonra rastgeleleştirme, grafikler, localStorage ve erişilebilirlik ekleyerek projenizi gerçek bir interaktif araştırma aracına dönüştürebilirsiniz.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="JavaScript" /><category term="DOM Manipülasyonu" /><category term="Kullanıcı Davranışı" /><category term="Psikoloji Testleri" /><summary type="html"><![CDATA[Tarayıcı, sadece butonlara tıkladığımız bir ekran değil; aynı zamanda küçük ölçekli davranış deneyleri yapabileceğimiz harika bir laboratuvardır. JavaScript sayesinde kullanıcıların seçimlerini, tepki sürelerini, dikkat kaymalarını ve karar örüntülerini analiz eden etkileşimli psikoloji ya da zeka testleri tasarlayabiliriz. Elbette burada amaç “insanı çözmek” değil; etik sınırlar içinde, anonim ve öğretici deneyimler üretmektir.]]></summary></entry></feed>