<?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://program.sonsuz.us/feed.xml" rel="self" type="application/atom+xml" /><link href="https://program.sonsuz.us/" rel="alternate" type="text/html" /><updated>2026-10-21T12:05:54+00:00</updated><id>https://program.sonsuz.us/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# İstisna Yönetimi: try-catch-finally ile Hataları Kontrol Altına Almak</title><link href="https://program.sonsuz.us/posts/c-istisna-yonetimi-try-catch-finally-ile-hatalari-kontrol-altina-almak/" rel="alternate" type="text/html" title="C# İstisna Yönetimi: try-catch-finally ile Hataları Kontrol Altına Almak" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-istisna-yonetimi-try-catch-finally-ile-hatalari-kontrol-altina-almak</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-istisna-yonetimi-try-catch-finally-ile-hatalari-kontrol-altina-almak/"><![CDATA[<p>Bir uygulamanın hiç hata üretmemesi neredeyse imkânsızdır; önemli olan, hata ortaya çıktığında sistemin nasıl davrandığıdır. C# istisna yönetimi, beklenmeyen durumları ana program akışından ayırarak uygulamanın kontrollü biçimde tepki vermesini sağlar. Dosya bulunamaması, ağ bağlantısının kesilmesi veya geçersiz kullanıcı girdisi artık birer felaket değil, yönetilebilir senaryolardır.
``</p>
<h2 id="i̇stisna-nedir">İstisna nedir?</h2>

<p>İstisna, program çalışırken normal akışı bozan olağan dışı bir durumu temsil eden nesnedir. C# içerisindeki bütün istisnalar doğrudan veya dolaylı olarak <code class="language-plaintext highlighter-rouge">System.Exception</code> sınıfından türetilir.</p>

<p>Bir işlemin başarısız olma olasılığını $P(E)$, hatanın sisteme vereceği zararı da $C(E)$ ile gösterirsek basitleştirilmiş risk hesabı şöyle yazılabilir:</p>

\[R = P(E) \times C(E)\]

<p>İstisna yönetimi hatanın oluşma ihtimalini her zaman azaltmaz; fakat $C(E)$ değerini düşürerek hatanın uygulamanın tamamına yayılmasını engeller.</p>

<table>
  <thead>
    <tr>
      <th>Yapı</th>
      <th>Görevi</th>
      <th>Ne zaman çalışır?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">try</code></td>
      <td>Riskli kodu çevreler</td>
      <td>Her denemede</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">catch</code></td>
      <td>Belirli istisnayı yakalar</td>
      <td>Eşleşen hata oluştuğunda</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">finally</code></td>
      <td>Kaynak temizliği yapar</td>
      <td>Hata olsa da olmasa da</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">throw</code></td>
      <td>İstisna oluşturur veya yeniden fırlatır</td>
      <td>Koşul sağlandığında</td>
    </tr>
  </tbody>
</table>

<h2 id="try-catch-finally-mimarisi">try-catch-finally mimarisi</h2>

<p>Aşağıdaki örnek bir dosyayı okumayı dener, olası hataları türlerine göre izole eder ve işlem sonunda bilgi verir:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">try</span>
<span class="p">{</span>
    <span class="kt">string</span> <span class="n">metin</span> <span class="p">=</span> <span class="n">File</span><span class="p">.</span><span class="nf">ReadAllText</span><span class="p">(</span><span class="s">"ayarlar.json"</span><span class="p">);</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">metin</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="n">FileNotFoundException</span> <span class="n">ex</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Dosya bulunamadı: </span><span class="p">{</span><span class="n">ex</span><span class="p">.</span><span class="n">FileName</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="n">UnauthorizedAccessException</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Dosyaya erişim yetkiniz yok."</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="n">IOException</span> <span class="n">ex</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Girdi/çıktı hatası: </span><span class="p">{</span><span class="n">ex</span><span class="p">.</span><span class="n">Message</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">finally</span>
<span class="p">{</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Dosya okuma denemesi tamamlandı."</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">catch</code> blokları özelden genele doğru sıralanmalıdır. Önce <code class="language-plaintext highlighter-rouge">Exception</code> yakalanırsa daha özel bloklara sıra gelmez. Ayrıca her yerde genel <code class="language-plaintext highlighter-rouge">Exception</code> yakalayıp hatayı sessizce yutmak, yangın alarmının pilini çıkarmaya benzer: ortam sessizleşir ama yangın devam eder.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Özel istisnayı yakalamak</td>
      <td>Anlamlı ve hedefli tepki sağlar</td>
      <td>Daha fazla blok gerektirebilir</td>
    </tr>
    <tr>
      <td>Genel <code class="language-plaintext highlighter-rouge">Exception</code> yakalamak</td>
      <td>Son savunma hattı oluşturur</td>
      <td>Gerçek hata nedenini gizleyebilir</td>
    </tr>
    <tr>
      <td>Hatayı yutmak</td>
      <td>Akış görünürde sürer</td>
      <td>Teşhis ve veri güvenliği zorlaşır</td>
    </tr>
    <tr>
      <td>Loglayıp yeniden fırlatmak</td>
      <td>Katmanlar arası görünürlük sağlar</td>
      <td>Aynı hata birden fazla kez loglanabilir</td>
    </tr>
  </tbody>
</table>

<p>Bir istisnayı aynı çağrı yığını bilgisiyle yeniden göndermek için <code class="language-plaintext highlighter-rouge">throw;</code> kullanılmalıdır. <code class="language-plaintext highlighter-rouge">throw ex;</code> ifadesi yığın izini değiştirerek hatanın gerçek kaynağını bulmayı zorlaştırabilir.</p>

<h2 id="özel-hata-sınıfları">Özel hata sınıfları</h2>

<p>İş kuralları için hazır istisnalar her zaman yeterince açıklayıcı değildir. Örneğin stok miktarının yetersiz olması teknik değil, alan odaklı bir problemdir:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">YetersizStokException</span> <span class="p">:</span> <span class="n">Exception</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="n">MevcutStok</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>

    <span class="k">public</span> <span class="nf">YetersizStokException</span><span class="p">(</span><span class="kt">string</span> <span class="n">mesaj</span><span class="p">,</span> <span class="kt">int</span> <span class="n">mevcutStok</span><span class="p">)</span>
        <span class="p">:</span> <span class="k">base</span><span class="p">(</span><span class="n">mesaj</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">MevcutStok</span> <span class="p">=</span> <span class="n">mevcutStok</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">SiparisVer</span><span class="p">(</span><span class="kt">int</span> <span class="n">istenen</span><span class="p">,</span> <span class="kt">int</span> <span class="n">stok</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">istenen</span> <span class="p">&gt;</span> <span class="n">stok</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nf">YetersizStokException</span><span class="p">(</span>
            <span class="s">"İstenen miktar stoktan fazla."</span><span class="p">,</span> <span class="n">stok</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu sınıf, hataya yalnızca mesaj değil, <code class="language-plaintext highlighter-rouge">MevcutStok</code> gibi yapılandırılmış bağlam da ekler. Üst katman böylece kullanıcıya uygun bildirim gösterebilir veya işlemi başka bir depoya yönlendirebilir.</p>

<h2 id="sağlam-kullanım-ilkeleri">Sağlam kullanım ilkeleri</h2>

<ul>
  <li>İstisnaları yalnızca gerçekten olağan dışı durumlarda kullanın; normal kontrol akışını <code class="language-plaintext highlighter-rouge">throw</code> ile kurmayın.</li>
  <li><code class="language-plaintext highlighter-rouge">ArgumentException</code>, <code class="language-plaintext highlighter-rouge">InvalidOperationException</code> ve <code class="language-plaintext highlighter-rouge">FileNotFoundException</code> gibi uygun hazır türleri tercih edin.</li>
  <li>Hataları bağlam bilgisiyle loglayın; parola ve erişim anahtarı gibi hassas verileri kaydetmeyin.</li>
  <li><code class="language-plaintext highlighter-rouge">IDisposable</code> kaynaklarında mümkünse <code class="language-plaintext highlighter-rouge">using</code> kullanın; derleyici gerekli temizliği güvenli biçimde oluşturur.</li>
  <li>Kullanıcıya sade mesaj, geliştiriciye ise ayrıntılı log sağlayın.</li>
</ul>

<p>Doğru tasarlanmış istisna yönetimi hataları yok etmez; onları sınırlar, görünür kılar ve uygulamanın güvenli biçimde toparlanmasına yardımcı olur. Kısacası <code class="language-plaintext highlighter-rouge">try-catch-finally</code>, kodun emniyet kemeridir: kazayı engellemeyebilir ama sonucunu ciddi ölçüde kontrol eder.</p>

<p><img src="/img/c-istisna-yonetimi-11.svg" alt="c-istisna-yonetimi-11" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="csharp" /><category term="exception" /><category term="hata-yönetimi" /><category term="try-catch" /><category term="dotnet" /><category term="özel-istisnalar" /><summary type="html"><![CDATA[Bir uygulamanın hiç hata üretmemesi neredeyse imkânsızdır; önemli olan, hata ortaya çıktığında sistemin nasıl davrandığıdır. C# istisna yönetimi, beklenmeyen durumları ana program akışından ayırarak uygulamanın kontrollü biçimde tepki vermesini sağlar. Dosya bulunamaması, ağ bağlantısının kesilmesi veya geçersiz kullanıcı girdisi artık birer felaket değil, yönetilebilir senaryolardır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-istisna-yonetimi-11.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-istisna-yonetimi-11.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++’ta Statik ve Dinamik Bağlamayı Karıştırınca Patlayan Tasarımlar</title><link href="https://program.sonsuz.us/posts/cta-statik-ve-dinamik-baglamayi-karistirinca-patlayan-tasarimlar/" rel="alternate" type="text/html" title="C++’ta Statik ve Dinamik Bağlamayı Karıştırınca Patlayan Tasarımlar" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/cta-statik-ve-dinamik-baglamayi-karistirinca-patlayan-tasarimlar</id><content type="html" xml:base="https://program.sonsuz.us/posts/cta-statik-ve-dinamik-baglamayi-karistirinca-patlayan-tasarimlar/"><![CDATA[<p>C++’ta bir fonksiyon çağrısının hangi gövdeye gideceği her zaman göründüğü kadar basit değildir. Derleyici bazen kararı derleme zamanında verir, bazen de çalışma zamanındaki gerçek nesne türüne bakar. Statik ve dinamik bağlamayı aynı tasarım içinde bilinçsizce karıştırmak; yanlış fonksiyonların çağrılmasına, kaynak sızıntılarına ve “Ama bu sınıfı ezmiştim!” şaşkınlığına yol açabilir.</p>

<p><img src="/img/cta-statik-ve-16.svg" alt="cta-statik-ve-16" /></p>

<p>``</p>

<h2 id="bağlama-tam-olarak-nedir">Bağlama tam olarak nedir?</h2>

<p>Bağlama, bir çağrı ifadesinin çalıştırılacak fonksiyon gövdesiyle eşleştirilmesidir. Statik bağlamada karar, değişkenin derleme zamanındaki türüne göre verilir. Dinamik bağlamada ise <code class="language-plaintext highlighter-rouge">virtual</code> mekanizması üzerinden nesnenin çalışma zamanındaki gerçek türü kullanılır.</p>

<p>Bunu kabaca şöyle düşünebiliriz:</p>

\[secim = f(T_{statik}, T_{dinamik}, virtual)\]

<p>Fonksiyon sanal değilse çoğunlukla $T_{statik}$ belirleyicidir. Sanal fonksiyon çağrısında ise uygun koşullarda $T_{dinamik}$ devreye girer.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Statik bağlama</th>
      <th>Dinamik bağlama</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Karar zamanı</td>
      <td>Derleme zamanı</td>
      <td>Çalışma zamanı</td>
    </tr>
    <tr>
      <td>Temel ölçüt</td>
      <td>İfadenin statik türü</td>
      <td>Nesnenin gerçek türü</td>
    </tr>
    <tr>
      <td>Tipik araçlar</td>
      <td>Overload, normal metot</td>
      <td><code class="language-plaintext highlighter-rouge">virtual</code>, <code class="language-plaintext highlighter-rouge">override</code></td>
    </tr>
    <tr>
      <td>Maliyet</td>
      <td>Genellikle doğrudan çağrı</td>
      <td>Genellikle sanal tablo erişimi</td>
    </tr>
    <tr>
      <td>Yaygın risk</td>
      <td>Yanlış overload seçimi</td>
      <td>Hatalı yaşam döngüsü tasarımı</td>
    </tr>
  </tbody>
</table>

<h2 id="hata-1-sanal-olmayan-yıkıcı">Hata 1: Sanal olmayan yıkıcı</h2>

<p>Polimorfik bir taban sınıfın yıkıcısını sanal yapmamak, en tehlikeli karışıklıklardan biridir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">Kaynak</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="o">~</span><span class="n">Kaynak</span><span class="p">()</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Kaynak kapandı</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span> <span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Dosya</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Kaynak</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="o">~</span><span class="n">Dosya</span><span class="p">()</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Dosya kapandı</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span> <span class="p">}</span>
<span class="p">};</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">Kaynak</span><span class="o">*</span> <span class="n">kaynak</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Dosya</span><span class="p">;</span>
    <span class="k">delete</span> <span class="n">kaynak</span><span class="p">;</span> <span class="c1">// Tanımsız davranış!</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">delete</code> işlemi taban işaretçisi üzerinden yapıldığı için yıkıcının dinamik davranması gerekir. Çözüm basittir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">virtual</span> <span class="o">~</span><span class="n">Kaynak</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
</code></pre></div></div>

<p>Bir sınıfta sanal metot varsa yıkıcının da genellikle sanal olması beklenir.</p>

<h2 id="hata-2-varsayılan-argümanların-sanal-olduğunu-sanmak">Hata 2: Varsayılan argümanların sanal olduğunu sanmak</h2>

<p>Sanal fonksiyonun gövdesi dinamik, varsayılan argümanı ise statik olarak seçilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span>
<span class="k">struct</span> <span class="nc">Bildirim</span> <span class="p">{</span>
    <span class="k">virtual</span> <span class="kt">void</span> <span class="n">gonder</span><span class="p">(</span><span class="kt">int</span> <span class="n">oncelik</span> <span class="o">=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">oncelik</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">Alarm</span> <span class="o">:</span> <span class="n">Bildirim</span> <span class="p">{</span>
    <span class="kt">void</span> <span class="n">gonder</span><span class="p">(</span><span class="kt">int</span> <span class="n">oncelik</span> <span class="o">=</span> <span class="mi">9</span><span class="p">)</span> <span class="k">override</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">oncelik</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">Alarm</span> <span class="n">alarm</span><span class="p">;</span>
    <span class="n">Bildirim</span><span class="o">&amp;</span> <span class="n">b</span> <span class="o">=</span> <span class="n">alarm</span><span class="p">;</span>
    <span class="n">b</span><span class="p">.</span><span class="n">gonder</span><span class="p">();</span> <span class="c1">// Alarm::gonder çalışır, fakat argüman 1 olur.</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Ortaya hibrit bir sonuç çıkar: gövde alt sınıftan, değer taban sınıftan gelir. Varsayılan değeri tek yerde tanımlamak veya parametresiz ayrı bir sanal olmayan arayüz kullanmak daha güvenlidir.</p>

<h2 id="hata-3-kurucuda-sanal-çağrı">Hata 3: Kurucuda sanal çağrı</h2>

<p>Kurucu sırasında nesnenin alt sınıf bölümü henüz hazır değildir. Bu nedenle taban kurucusundan yapılan sanal çağrı, alt sınıf sürümüne gitmez:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="nc">Motor</span> <span class="p">{</span>
    <span class="n">Motor</span><span class="p">()</span> <span class="p">{</span> <span class="n">baslat</span><span class="p">();</span> <span class="p">}</span>
    <span class="k">virtual</span> <span class="kt">void</span> <span class="nf">baslat</span><span class="p">()</span> <span class="p">{</span> <span class="cm">/* taban davranışı */</span> <span class="p">}</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">TurboMotor</span> <span class="o">:</span> <span class="n">Motor</span> <span class="p">{</span>
    <span class="kt">void</span> <span class="n">baslat</span><span class="p">()</span> <span class="k">override</span> <span class="p">{</span> <span class="cm">/* turbo henüz hazır olmayabilir */</span> <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Nesneyi oluşturduktan sonra çağrılan bir <code class="language-plaintext highlighter-rouge">initialize()</code> metodu veya fabrika fonksiyonu kullanmak daha açık bir yaşam döngüsü sağlar.</p>

<h2 id="hata-4-nesne-dilimleme">Hata 4: Nesne dilimleme</h2>

<p>Alt sınıf nesnesini değer olarak taban türe kopyalamak dinamik tür bilgisini keser:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">calistir</span><span class="p">(</span><span class="n">Motor</span> <span class="n">motor</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Kopyalama ve dilimleme</span>
    <span class="n">motor</span><span class="p">.</span><span class="n">baslat</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bunun yerine <code class="language-plaintext highlighter-rouge">Motor&amp;</code>, <code class="language-plaintext highlighter-rouge">Motor*</code> veya uygun bir akıllı işaretçi kullanılmalıdır.</p>

<h2 id="sağlam-tasarım-kontrol-listesi">Sağlam tasarım kontrol listesi</h2>

<ul>
  <li>Ezilen her metoda <code class="language-plaintext highlighter-rouge">override</code> ekleyin.</li>
  <li>Polimorfik tabanlarda sanal yıkıcı kullanın.</li>
  <li>Sanal metotlarda farklı varsayılan argümanlardan kaçının.</li>
  <li>Kurucu ve yıkıcılarda sanal dispatch’e güvenmeyin.</li>
  <li>Polimorfik nesneleri değer yerine referans veya işaretçiyle taşıyın.</li>
  <li>Overload ile override kavramlarını aynı şey sanmayın.</li>
</ul>

<p>Kısacası <code class="language-plaintext highlighter-rouge">virtual</code>, tasarıma sihir serpiştiren bir kelime değildir. Hangi kararın derleyiciye, hangisinin çalışma zamanına bırakıldığını açıkça belirlemek gerekir; aksi hâlde kod derlenir, çalışır ve tam en kötü anda yanlış şeyi yapar.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="binding" /><category term="polimorfizm" /><category term="oop" /><category term="tasarım-hataları" /><category term="virtual" /><summary type="html"><![CDATA[C++’ta bir fonksiyon çağrısının hangi gövdeye gideceği her zaman göründüğü kadar basit değildir. Derleyici bazen kararı derleme zamanında verir, bazen de çalışma zamanındaki gerçek nesne türüne bakar. Statik ve dinamik bağlamayı aynı tasarım içinde bilinçsizce karıştırmak; yanlış fonksiyonların çağrılmasına, kaynak sızıntılarına ve “Ama bu sınıfı ezmiştim!” şaşkınlığına yol açabilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/cta-statik-ve-16.png" /><media:content medium="image" url="https://program.sonsuz.us/img/cta-statik-ve-16.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Humanoid Robotlarda Dengeli Adımlar: Yürüme Döngüsünde Faz Analizi</title><link href="https://program.sonsuz.us/posts/humanoid-robotlarda-dengeli-adimlar-yurume-dongusunde-faz-analizi/" rel="alternate" type="text/html" title="Humanoid Robotlarda Dengeli Adımlar: Yürüme Döngüsünde Faz Analizi" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/humanoid-robotlarda-dengeli-adimlar-yurume-dongusunde-faz-analizi</id><content type="html" xml:base="https://program.sonsuz.us/posts/humanoid-robotlarda-dengeli-adimlar-yurume-dongusunde-faz-analizi/"><![CDATA[<p>İnsansı bir robotun yürümesi, uzaktan bakıldığında sırayla sağ ve sol ayağı öne atmaktan ibaret görünebilir. Oysa robot açısından her adım; temas kuvvetleri, gövde momentumu, eklem açıları ve zamanlamanın birlikte yönetildiği dinamik bir denge problemidir. Faz analizi, robotun bu karmaşık hareketin neresinde bulunduğunu ve küçük bir bozucudan sonra güvenli döngüsüne dönüp dönemeyeceğini anlamamızı sağlar.
``</p>

<h2 id="yürüme-döngüsü-neden-periyodiktir">Yürüme döngüsü neden periyodiktir?</h2>

<p>Bir gait cycle, aynı ayağın iki benzer teması arasındaki hareket dizisidir. Döngü genellikle <strong>tek destek</strong>, <strong>çift destek</strong>, <strong>salınım</strong> ve <strong>temas geçişi</strong> evrelerine ayrılır. Eklem açıları tam olarak tekrarlanmasa bile sistem durumunun benzer bir yörüngeyi izlemesi beklenir.</p>

<p>Robotun durumu şu vektörle gösterilebilir:</p>

\[\mathbf{x}(t)=[\mathbf{q}(t),\dot{\mathbf{q}}(t)]^T\]

<p>Burada $\mathbf{q}$ eklem konumlarını, $\dot{\mathbf{q}}$ ise hızları temsil eder. Kararlı yürüyüşte durum uzayındaki hareket, <strong>limit döngü</strong> adı verilen kapalı bir yörünge oluşturur. Robot küçük bir itme aldığında yörüngeden uzaklaşabilir; önemli olan birebir aynı noktaya değil, tekrar bu döngüye yaklaşmasıdır. Buna <strong>yörüngesel kararlılık</strong> denir.</p>

<h2 id="zaman-değil-faz-neden-önemlidir">Zaman değil, faz neden önemlidir?</h2>

<p>Sadece saate bakarak “robot adımın yüzde 40’ında” demek yanıltıcı olabilir. Yokuş, zemin esnekliği veya dışarıdan gelen bir itme adım süresini değiştirir. Faz değişkeni ise hareketin fiziksel ilerleyişini takip eder:</p>

\[\phi \in [0,2\pi), \qquad \dot{\phi}=\omega\]

<p>Örneğin kalça açısı ve açısal hızı birlikte kullanılarak faz düzleminde bir yörünge çizilebilir. Böylece kontrolcü, kronometreden bağımsız biçimde ayağın salınımın başında mı yoksa yere temas etmek üzere mi olduğunu anlayabilir.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>İzlenen bilgi</th>
      <th>Bozuculara tepki</th>
      <th>Temel risk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Zaman tabanlı kontrol</td>
      <td>Geçen süre</td>
      <td>Sınırlı uyum</td>
      <td>Hareket ile saat ayrışabilir</td>
    </tr>
    <tr>
      <td>Olay tabanlı kontrol</td>
      <td>Topuk teması gibi olaylar</td>
      <td>Temaslarda güçlü</td>
      <td>İki olay arasında az bilgi verir</td>
    </tr>
    <tr>
      <td>Faz tabanlı kontrol</td>
      <td>Döngüdeki sürekli ilerleme</td>
      <td>Yüksek uyum</td>
      <td>Güvenilir faz kestirimi gerekir</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/humanoid-robotlarda-dengeli-62.svg" alt="humanoid-robotlarda-dengeli-62" /></p>

<h2 id="kararlılık-nasıl-ölçülür">Kararlılık nasıl ölçülür?</h2>

<p>Yürümenin belirli bir olayında, örneğin sağ topuk temasında, sistem durumu örneklenebilir. Bu kesite <strong>Poincaré kesiti</strong> denir. Ardışık adımlar arasındaki ilişki</p>

\[\mathbf{x}_{k+1}=P(\mathbf{x}_k)\]

<p>şeklinde yazılır. Sabit yürüyüş için $\mathbf{x}^<em>=P(\mathbf{x}^</em>)$ olmalıdır. Haritanın sabit nokta çevresindeki özdeğerleri, yani Floquet çarpanları, kritik bilgiyi verir. Baskın çarpanın mutlak değeri $\vert \lambda_{max}\vert &lt;1$ ise sapmalar küçülür; $\vert \lambda_{max}\vert &gt;1$ ise robot birkaç adım sonra dramatik bir “yerçekimiyle tanışma” yaşayabilir.</p>

<h2 id="basit-bir-faz-portresi">Basit bir faz portresi</h2>

<p>Aşağıdaki Python kodu, idealize edilmiş bir eklem hareketinin açı-hız faz portresini üretir. Kapalı eğri, periyodik davranışın görsel imzasıdır:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="kn">import</span> <span class="n">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span>

<span class="c1"># Bir adımlık örnek kalça açısı
</span><span class="n">phase</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="n">pi</span><span class="p">,</span> <span class="mi">500</span><span class="p">)</span>
<span class="n">angle</span> <span class="o">=</span> <span class="mf">0.35</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="nf">sin</span><span class="p">(</span><span class="n">phase</span><span class="p">)</span>
<span class="n">angular_velocity</span> <span class="o">=</span> <span class="mf">0.35</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="nf">cos</span><span class="p">(</span><span class="n">phase</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="nf">plot</span><span class="p">(</span><span class="n">angle</span><span class="p">,</span> <span class="n">angular_velocity</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">xlabel</span><span class="p">(</span><span class="sh">"</span><span class="s">Eklem açısı (rad)</span><span class="sh">"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">ylabel</span><span class="p">(</span><span class="sh">"</span><span class="s">Açısal hız (rad/s)</span><span class="sh">"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">title</span><span class="p">(</span><span class="sh">"</span><span class="s">Kalça Eklemi Faz Portresi</span><span class="sh">"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">grid</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">axis</span><span class="p">(</span><span class="sh">"</span><span class="s">equal</span><span class="sh">"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">show</span><span class="p">()</span>
</code></pre></div></div>

<p>Gerçek robotta eğrinin kalınlaşması sensör gürültüsünü, giderek genişlemesi kararsızlığı, bozucu sonrası yeniden daralması ise toparlanmayı gösterebilir. Bu analiz; ZMP, basınç merkezi ve gövde kütle merkezi ölçümleriyle birleştirildiğinde daha anlamlı hâle gelir.</p>

<h2 id="kontrolcüye-sağladığı-avantaj">Kontrolcüye sağladığı avantaj</h2>

<p>Faz analizi sayesinde kontrol sistemi ayağın yere temas zamanını ayarlayabilir, adım uzunluğunu değiştirebilir ve gövde momentumunu dengeleyebilir. Ayrıca farklı hızlardaki yürüyüşler tek bir faz koordinatında karşılaştırılabilir. Kısacası faz, robotun yalnızca <strong>ne yaptığını</strong> değil, hareketin <strong>hangi bölümünde ve ne kadar kararlı biçimde</strong> yaptığını söyler. Dengeli bir humanoid için doğru adım kadar, doğru anda atılan adım da belirleyicidir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="humanoid" /><category term="yürüme-döngüsü" /><category term="faz-analizi" /><category term="kararlılık" /><category term="kontrol-sistemleri" /><summary type="html"><![CDATA[İnsansı bir robotun yürümesi, uzaktan bakıldığında sırayla sağ ve sol ayağı öne atmaktan ibaret görünebilir. Oysa robot açısından her adım; temas kuvvetleri, gövde momentumu, eklem açıları ve zamanlamanın birlikte yönetildiği dinamik bir denge problemidir. Faz analizi, robotun bu karmaşık hareketin neresinde bulunduğunu ve küçük bir bozucudan sonra güvenli döngüsüne dönüp dönemeyeceğini anlamamızı sağlar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/humanoid-robotlarda-dengeli-62.png" /><media:content medium="image" url="https://program.sonsuz.us/img/humanoid-robotlarda-dengeli-62.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">İki Bacaklı Robotlarda Ters Sarkaç ile Denge Kontrolü</title><link href="https://program.sonsuz.us/posts/iki-bacakli-robotlarda-ters-sarkac-ile-denge-kontrolu/" rel="alternate" type="text/html" title="İki Bacaklı Robotlarda Ters Sarkaç ile Denge Kontrolü" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/iki-bacakli-robotlarda-ters-sarkac-ile-denge-kontrolu</id><content type="html" xml:base="https://program.sonsuz.us/posts/iki-bacakli-robotlarda-ters-sarkac-ile-denge-kontrolu/"><![CDATA[<p><img src="/img/iki-bacakli-robotlarda-52.svg" alt="iki-bacakli-robotlarda-52" /></p>

<p>İki bacak üzerinde yürümek insanlar için sıradan, robotlar için ise sürekli çözülmesi gereken bir denge problemidir. Robotun kütle merkezi destek alanının dışına çıktığında yer çekimi hemen devreye girer ve pahalı metal kahramanımız yere doğru dramatik bir yolculuğa başlar. Ters sarkaç modeli, bu karmaşık gövde ve eklem sistemini daha anlaşılır bir fizik problemine dönüştürerek denge denetleyicilerinin tasarlanmasını kolaylaştırır.</p>

<p>``</p>

<h2 id="robot-neden-ters-sarkaç-olarak-modellenir">Robot neden ters sarkaç olarak modellenir?</h2>

<p>Klasik sarkaçta kütle aşağıdadır ve sistem doğal olarak kararlı durumuna dönmek ister. Ters sarkaçta ise kütle dönme noktasının üzerindedir. Küçük bir eğim bile kütlenin daha fazla uzaklaşmasına yol açar. İki bacaklı robot da ayakları üzerinde dururken benzer biçimde <strong>doğal olarak kararsızdır</strong>.</p>

<p>Basitleştirilmiş modelde robotun toplam kütlesi, kütle merkezinde bulunan noktasal bir $m$ kütlesi olarak kabul edilir. Bacak ise uzunluğu $l$ olan, kütlesiz bir çubuk gibi düşünülür. Robotun dikey eksene göre açısı $\theta$ ise temel dinamik yaklaşık olarak şöyledir:</p>

\[ml^2\ddot{\theta}=mgl\sin(\theta)+\tau\]

<p>Burada $g$ yer çekimi ivmesini, $\tau$ ise ayak bileği veya eş değer eklem torkunu gösterir. Denge çevresindeki küçük açılarda $\sin(\theta)\approx\theta$ kabulü yapılabilir:</p>

\[\ddot{\theta}\approx\frac{g}{l}\theta+\frac{1}{ml^2}\tau\]

<p>$\theta$ katsayısının pozitif olması kritik ayrıntıdır: kontrol uygulanmazsa eğim kendiliğinden büyür.</p>

<h2 id="basitleştirme-seçenekleri">Basitleştirme seçenekleri</h2>

<table>
  <thead>
    <tr>
      <th>Model</th>
      <th>Varsayım</th>
      <th>Avantaj</th>
      <th>Sınırlama</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ters sarkaç</td>
      <td>Tek dönme noktası ve sabit bacak</td>
      <td>Basit kontrol tasarımı</td>
      <td>Yürüyüş ayrıntılarını az temsil eder</td>
    </tr>
    <tr>
      <td>Doğrusal ters sarkaç</td>
      <td>Kütle merkezi yüksekliği sabittir</td>
      <td>ZMP ve adım planlamada hızlıdır</td>
      <td>Dikey hareketleri ihmal eder</td>
    </tr>
    <tr>
      <td>Çok bağlantılı model</td>
      <td>Gövde ve eklemler ayrıdır</td>
      <td>Daha gerçekçi sonuç verir</td>
      <td>Hesaplama maliyeti yüksektir</td>
    </tr>
  </tbody>
</table>

<p>Özellikle <strong>Doğrusal Ters Sarkaç Modeli</strong> (LIPM), kütle merkezinin yatay hareketini incelemek için kullanılır. Sabit $z_c$ yüksekliğinde yatay dinamik:</p>

\[\ddot{x}=\frac{g}{z_c}(x-p)\]

<p>şeklindedir. Buradaki $x$ kütle merkezinin yatay konumu, $p$ ise basınç merkezi veya ideal koşullarda Zero Moment Point (ZMP) konumudur. Dengeyi korumak için $p$ değerinin ayağın oluşturduğu destek çokgeni içinde kalması gerekir.</p>

<h2 id="denetleyici-nasıl-müdahale-eder">Denetleyici nasıl müdahale eder?</h2>

<p>Robot; IMU, eklem enkoderleri ve ayak tabanı kuvvet sensörlerinden veri toplar. Bu ölçümlerle açı, açısal hız ve kütle merkezi durumu tahmin edilir. Ardından PID, durum geri besleme veya LQR gibi bir denetleyici düzeltici tork üretir.</p>

<p>Durum vektörü $X=[\theta,\dot{\theta}]^T$ seçildiğinde LQR yaklaşımı</p>

\[u=-KX\]

<p>kontrol yasasını kullanır. $K$ kazancı, açı hatası ile enerji tüketimi arasında sistematik bir denge kurar. Aşağıdaki Python örneği, basitleştirilmiş bir geri besleme döngüsünü simüle eder:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="n">m</span><span class="p">,</span> <span class="n">l</span><span class="p">,</span> <span class="n">g</span> <span class="o">=</span> <span class="mf">20.0</span><span class="p">,</span> <span class="mf">0.8</span><span class="p">,</span> <span class="mf">9.81</span>
<span class="n">dt</span> <span class="o">=</span> <span class="mf">0.002</span>
<span class="n">K</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">array</span><span class="p">([</span><span class="mf">450.0</span><span class="p">,</span> <span class="mf">90.0</span><span class="p">])</span>
<span class="n">state</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">array</span><span class="p">([</span><span class="mf">0.12</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">])</span>  <span class="c1"># açı ve açısal hız
</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="mi">3000</span><span class="p">):</span>
    <span class="n">theta</span><span class="p">,</span> <span class="n">omega</span> <span class="o">=</span> <span class="n">state</span>
    <span class="n">torque</span> <span class="o">=</span> <span class="o">-</span><span class="n">K</span> <span class="o">@</span> <span class="n">state</span>
    <span class="n">acceleration</span> <span class="o">=</span> <span class="p">(</span><span class="n">g</span> <span class="o">/</span> <span class="n">l</span><span class="p">)</span> <span class="o">*</span> <span class="n">theta</span> <span class="o">+</span> <span class="n">torque</span> <span class="o">/</span> <span class="p">(</span><span class="n">m</span> <span class="o">*</span> <span class="n">l</span><span class="o">**</span><span class="mi">2</span><span class="p">)</span>

    <span class="n">omega</span> <span class="o">+=</span> <span class="n">acceleration</span> <span class="o">*</span> <span class="n">dt</span>
    <span class="n">theta</span> <span class="o">+=</span> <span class="n">omega</span> <span class="o">*</span> <span class="n">dt</span>
    <span class="n">state</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">array</span><span class="p">([</span><span class="n">theta</span><span class="p">,</span> <span class="n">omega</span><span class="p">])</span>

<span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Son açı: </span><span class="si">{</span><span class="n">np</span><span class="p">.</span><span class="nf">degrees</span><span class="p">(</span><span class="n">state</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="si">:</span><span class="p">.</span><span class="mi">4</span><span class="n">f</span><span class="si">}</span><span class="s"> derece</span><span class="sh">"</span><span class="p">)</span>
</code></pre></div></div>

<p>Kod, robot öne eğildiğinde ters yönde tork uygulayarak açıyı sıfıra yaklaştırır. Gerçek robotta tork sınırları, sensör gürültüsü, gecikme ve ayağın kayması da modele eklenmelidir.</p>

<h2 id="ayakta-durmaktan-yürümeye">Ayakta durmaktan yürümeye</h2>

<p>Yürüme sırasında destek noktası sürekli değişir. Denetleyici yalnızca mevcut düşüşü engellemez; bir sonraki ayağın nereye basacağını da planlar. Küçük bozucular ayak bileği torkuyla, daha büyük bozucular kalça hareketiyle, çok güçlü itmeler ise yeni bir adımla karşılanır. Böylece ters sarkaç modeli, kusursuz bir robot kopyası olmaktan ziyade, karmaşık denge problemini gerçek zamanlı çözülebilen kullanışlı bir haritaya dönüştürür.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="denge kontrolü" /><category term="ters sarkaç" /><category term="biped robot" /><category term="lqr" /><category term="zmp" /><summary type="html"><![CDATA[İki bacak üzerinde yürümek insanlar için sıradan, robotlar için ise sürekli çözülmesi gereken bir denge problemidir. Robotun kütle merkezi destek alanının dışına çıktığında yer çekimi hemen devreye girer ve pahalı metal kahramanımız yere doğru dramatik bir yolculuğa başlar. Ters sarkaç modeli, bu karmaşık gövde ve eklem sistemini daha anlaşılır bir fizik problemine dönüştürerek denge denetleyicilerinin tasarlanmasını kolaylaştırır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/iki-bacakli-robotlarda-52.png" /><media:content medium="image" url="https://program.sonsuz.us/img/iki-bacakli-robotlarda-52.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Python Çoklu Kalıtımında MRO: Metotlar Neden Beklenmedik Yere Gidiyor?</title><link href="https://program.sonsuz.us/posts/python-coklu-kalitiminda-mro-metotlar-neden-beklenmedik-yere-gidiyor/" rel="alternate" type="text/html" title="Python Çoklu Kalıtımında MRO: Metotlar Neden Beklenmedik Yere Gidiyor?" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/python-coklu-kalitiminda-mro-metotlar-neden-beklenmedik-yere-gidiyor</id><content type="html" xml:base="https://program.sonsuz.us/posts/python-coklu-kalitiminda-mro-metotlar-neden-beklenmedik-yere-gidiyor/"><![CDATA[<p>Python’da çoklu kalıtım ilk bakışta oldukça masum görünür: Bir sınıf, birden fazla sınıftan özellik kazanır ve herkes mutlu olur. Ancak aynı isimli metotlar, elmas biçimli kalıtım zincirleri ve <code class="language-plaintext highlighter-rouge">super()</code> çağrıları devreye girdiğinde Python’ın hangi metodu çalıştırdığı şaşırtıcı olabilir. Bu karar rastgele verilmez; arka planda Method Resolution Order, yani MRO adı verilen kesin bir sıralama bulunur.
``</p>
<h2 id="mro-tam-olarak-nedir">MRO tam olarak nedir?</h2>

<p>MRO, bir özellik veya metot aranırken sınıfların hangi sırayla ziyaret edileceğini belirtir. Python 3 bu sırayı oluşturmak için <strong>C3 doğrusallaştırma</strong> algoritmasını kullanır. Amaç; çocuk sınıfları ebeveynlerden önce tutmak, sınıf bildirimindeki soldan sağa önceliği korumak ve kalıtım ağında tutarlı bir sıra üretmektir.</p>

<p>Bir <code class="language-plaintext highlighter-rouge">C</code> sınıfı, <code class="language-plaintext highlighter-rouge">B1, B2, ..., Bn</code> sınıflarından türetiliyorsa sıralama kabaca şöyle ifade edilir:</p>

\[L(C) = [C] + merge(L(B_1), L(B_2), \ldots, L(B_n), [B_1, B_2, \ldots, B_n])\]

<p>Buradaki <code class="language-plaintext highlighter-rouge">merge</code>, başka listelerin kuyruklarında bulunmayan uygun bir baş elemanı seçer. Bu kural, bir sınıfın kendi alt sınıfından önce aranmasını engeller.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Arama mantığı</th>
      <th>Olası sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tekli kalıtım</td>
      <td>Çocuktan ebeveyne doğru</td>
      <td>Genellikle tahmin edilebilir</td>
    </tr>
    <tr>
      <td>Basit çoklu kalıtım</td>
      <td>Soldaki ebeveyn önce</td>
      <td>Aynı adlı metot gölgelenebilir</td>
    </tr>
    <tr>
      <td>Elmas kalıtım</td>
      <td>C3 MRO sırası izlenir</td>
      <td>Ortak ata yalnızca bir kez işlenir</td>
    </tr>
    <tr>
      <td>Doğrudan sınıf çağrısı</td>
      <td>Belirtilen sınıf zorla kullanılır</td>
      <td>Zincir ve diğer sınıflar atlanabilir</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/python-coklu-kalitiminda-68.svg" alt="python-coklu-kalitiminda-68" /></p>

<h2 id="beklenmedik-davranış-örneği">Beklenmedik davranış örneği</h2>

<p>Aşağıdaki örnekte iki ara sınıf aynı metodu değiştirir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Temel</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">mesaj</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="sh">"</span><span class="s">Temel</span><span class="sh">"</span>

<span class="k">class</span> <span class="nc">A</span><span class="p">(</span><span class="n">Temel</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">mesaj</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="sh">"</span><span class="s">A -&gt; </span><span class="sh">"</span> <span class="o">+</span> <span class="nf">super</span><span class="p">().</span><span class="nf">mesaj</span><span class="p">()</span>

<span class="k">class</span> <span class="nc">B</span><span class="p">(</span><span class="n">Temel</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">mesaj</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="sh">"</span><span class="s">B -&gt; </span><span class="sh">"</span> <span class="o">+</span> <span class="nf">super</span><span class="p">().</span><span class="nf">mesaj</span><span class="p">()</span>

<span class="k">class</span> <span class="nc">C</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="p">):</span>
    <span class="k">pass</span>

<span class="n">nesne</span> <span class="o">=</span> <span class="nc">C</span><span class="p">()</span>
<span class="nf">print</span><span class="p">(</span><span class="n">nesne</span><span class="p">.</span><span class="nf">mesaj</span><span class="p">())</span>
<span class="nf">print</span><span class="p">(</span><span class="n">C</span><span class="p">.</span><span class="nf">mro</span><span class="p">())</span>
</code></pre></div></div>

<p>Çıktı şu yapıdadır:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>A -&gt; B -&gt; Temel
[C, A, B, Temel, object]
</code></pre></div></div>

<p>Şaşırtıcı nokta, <code class="language-plaintext highlighter-rouge">A</code> içindeki <code class="language-plaintext highlighter-rouge">super()</code> çağrısının doğrudan <code class="language-plaintext highlighter-rouge">Temel</code> sınıfına gitmemesidir. <code class="language-plaintext highlighter-rouge">super()</code>, “ebeveynimi çağır” anlamına gelmez; <strong>mevcut MRO’da benden sonraki sınıfa geç</strong> demektir. Dolayısıyla <code class="language-plaintext highlighter-rouge">C(A, B)</code> için <code class="language-plaintext highlighter-rouge">A</code> sonrasında <code class="language-plaintext highlighter-rouge">B</code> çalışır.</p>

<p>Ebeveynlerin sırasını değiştirirsek sonuç da değişir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">D</span><span class="p">(</span><span class="n">B</span><span class="p">,</span> <span class="n">A</span><span class="p">):</span>
    <span class="k">pass</span>

<span class="nf">print</span><span class="p">(</span><span class="nc">D</span><span class="p">().</span><span class="nf">mesaj</span><span class="p">())</span>
<span class="c1"># B -&gt; A -&gt; Temel
</span></code></pre></div></div>

<p>Yalnızca sınıf bildirimindeki sıra değişmesine rağmen davranış tersine dönmüştür. Özellikle mixin kullanılan büyük projelerde bu durum sessiz ve zor bulunan hatalar doğurabilir.</p>

<h2 id="super-zinciri-nasıl-güvenli-kurulur"><code class="language-plaintext highlighter-rouge">super()</code> zinciri nasıl güvenli kurulur?</h2>

<p>İşbirlikçi çoklu kalıtımda zincire katılan bütün sınıflar uyumlu davranmalıdır. Her sınıf <code class="language-plaintext highlighter-rouge">super()</code> çağırmalı, metot imzaları birbiriyle çelişmemeli ve zincir doğrudan sınıf adıyla kesilmemelidir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">KayitMixin</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">kaydet</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Kayıt günlüğü oluşturuldu</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">return</span> <span class="nf">super</span><span class="p">().</span><span class="nf">kaydet</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">DogrulamaMixin</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">kaydet</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">kwargs</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="sh">"</span><span class="s">ad</span><span class="sh">"</span><span class="p">):</span>
            <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">ad gerekli</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">return</span> <span class="nf">super</span><span class="p">().</span><span class="nf">kaydet</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">Depo</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">kaydet</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="k">return</span> <span class="sa">f</span><span class="sh">"</span><span class="s">Kaydedildi: </span><span class="si">{</span><span class="n">kwargs</span><span class="p">[</span><span class="sh">'</span><span class="s">ad</span><span class="sh">'</span><span class="p">]</span><span class="si">}</span><span class="sh">"</span>

<span class="k">class</span> <span class="nc">Servis</span><span class="p">(</span><span class="n">KayitMixin</span><span class="p">,</span> <span class="n">DogrulamaMixin</span><span class="p">,</span> <span class="n">Depo</span><span class="p">):</span>
    <span class="k">pass</span>
</code></pre></div></div>

<p>Bu tasarımda her katman yalnızca kendi görevini yapar ve kontrolü sıradaki sınıfa bırakır. <code class="language-plaintext highlighter-rouge">Servis.mro()</code> çağrısı, gerçek yürütme yolunu incelemenin en pratik yöntemidir.</p>

<h2 id="akılda-tutulması-gerekenler">Akılda tutulması gerekenler</h2>

<p>MRO’yu bir soy ağacından çok, Python’ın önceden hazırladığı bir ziyaret listesi gibi düşünün. <code class="language-plaintext highlighter-rouge">super()</code> bu listede tek adım ilerler. Beklenmedik bir sonuçla karşılaştığınızda <code class="language-plaintext highlighter-rouge">Sinif.__mro__</code> veya <code class="language-plaintext highlighter-rouge">Sinif.mro()</code> çıktısını kontrol edin; ebeveyn sırasını bilinçli belirleyin ve doğrudan <code class="language-plaintext highlighter-rouge">A.metot(self)</code> çağrılarından kaçının. Çoklu kalıtım güçlüdür, fakat MRO okunmadan kullanıldığında kod tabanına küçük bir labirent yerleştirebilir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="python" /><category term="mro" /><category term="çoklu-kalıtım" /><category term="oop" /><category term="c3-doğrusallaştırma" /><category term="super" /><summary type="html"><![CDATA[Python’da çoklu kalıtım ilk bakışta oldukça masum görünür: Bir sınıf, birden fazla sınıftan özellik kazanır ve herkes mutlu olur. Ancak aynı isimli metotlar, elmas biçimli kalıtım zincirleri ve super() çağrıları devreye girdiğinde Python’ın hangi metodu çalıştırdığı şaşırtıcı olabilir. Bu karar rastgele verilmez; arka planda Method Resolution Order, yani MRO adı verilen kesin bir sıralama bulunur.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/python-coklu-kalitiminda-68.png" /><media:content medium="image" url="https://program.sonsuz.us/img/python-coklu-kalitiminda-68.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Python Dekoratörlerinde Kimlik Krizi: functools.wraps ile Metadata’yı Korumak</title><link href="https://program.sonsuz.us/posts/python-dekoratorlerinde-kimlik-krizi-functoolswraps-ile-metadatayi-korumak/" rel="alternate" type="text/html" title="Python Dekoratörlerinde Kimlik Krizi: functools.wraps ile Metadata’yı Korumak" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/python-dekoratorlerinde-kimlik-krizi-functoolswraps-ile-metadatayi-korumak</id><content type="html" xml:base="https://program.sonsuz.us/posts/python-dekoratorlerinde-kimlik-krizi-functoolswraps-ile-metadatayi-korumak/"><![CDATA[<p>Python dekoratörleri, bir fonksiyonun davranışını kaynak kodunu değiştirmeden genişletmenin zarif bir yoludur. Ancak dekoratörümüzü dikkatsizce yazarsak orijinal fonksiyonun adı, docstring’i ve diğer metadata bilgileri ortadan kaybolabilir. Fonksiyon çalışmaya devam eder ama sahneye başka birinin kimliğiyle çıkar. Neyse ki <code class="language-plaintext highlighter-rouge">functools.wraps</code>, bu küçük kimlik krizini çözmek için standart kütüphanede bizi bekler.
``</p>
<h2 id="dekoratör-aslında-ne-yapar">Dekoratör aslında ne yapar?</h2>

<p>Bir dekoratör, bir fonksiyonu parametre olarak alır ve yerine genellikle başka bir fonksiyon döndürür. Matematiksel olarak dekoratör dönüşümünü şöyle düşünebiliriz:</p>

\[D(f) = g\]

<p>Burada $f$ orijinal fonksiyon, $D$ dekoratör ve $g$ çağrıların yönlendirildiği yeni fonksiyondur. Python’daki <code class="language-plaintext highlighter-rouge">@dekorator</code> sözdizimi ise temelde şu eşitliğin kısa yazımıdır:</p>

\[f = D(f)\]

<p>Basit bir zamanlama dekoratörü yazalım:</p>

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

<span class="k">def</span> <span class="nf">zaman_olc</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="n">baslangic</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="nf">perf_counter</span><span class="p">()</span>
        <span class="n">sonuc</span> <span class="o">=</span> <span class="nf">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
        <span class="n">sure</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="nf">perf_counter</span><span class="p">()</span> <span class="o">-</span> <span class="n">baslangic</span>
        <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Çalışma süresi: </span><span class="si">{</span><span class="n">sure</span><span class="si">:</span><span class="p">.</span><span class="mi">6</span><span class="n">f</span><span class="si">}</span><span class="s"> saniye</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">sonuc</span>

    <span class="k">return</span> <span class="n">wrapper</span>

<span class="nd">@zaman_olc</span>
<span class="k">def</span> <span class="nf">topla</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="sh">"""</span><span class="s">İki sayıyı toplar.</span><span class="sh">"""</span>
    <span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">wrapper</code>, farklı imzalara sahip fonksiyonlarla çalışabilmek için <code class="language-plaintext highlighter-rouge">*args</code> ve <code class="language-plaintext highlighter-rouge">**kwargs</code> kullanır. Önce zamanı kaydeder, orijinal fonksiyonu çalıştırır ve geçen süreyi ekrana yazar.</p>

<h2 id="metadata-neden-kaybolur">Metadata neden kaybolur?</h2>

<p>Dekoratör uygulandıktan sonra <code class="language-plaintext highlighter-rouge">topla</code> değişkeni artık orijinal fonksiyonu değil, döndürülen <code class="language-plaintext highlighter-rouge">wrapper</code> fonksiyonunu gösterir. Bu nedenle aşağıdaki sonuçlar şaşırtıcı olabilir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">print</span><span class="p">(</span><span class="n">topla</span><span class="p">.</span><span class="n">__name__</span><span class="p">)</span>  <span class="c1"># wrapper
</span><span class="nf">print</span><span class="p">(</span><span class="n">topla</span><span class="p">.</span><span class="n">__doc__</span><span class="p">)</span>   <span class="c1"># None
</span></code></pre></div></div>

<p>Python açısından ortada gizem yoktur: Yeni nesnenin metadata’sı okunmaktadır. Sorun özellikle dokümantasyon araçlarında, hata ayıklamada, testlerde ve fonksiyon adını kullanan framework’lerde belirginleşir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Dekoratörsüz</th>
      <th>Sıradan dekoratör sonrası</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">__name__</code></td>
      <td><code class="language-plaintext highlighter-rouge">topla</code></td>
      <td><code class="language-plaintext highlighter-rouge">wrapper</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">__doc__</code></td>
      <td><code class="language-plaintext highlighter-rouge">İki sayıyı toplar.</code></td>
      <td><code class="language-plaintext highlighter-rouge">None</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">__module__</code></td>
      <td>Tanımlandığı modül</td>
      <td>Dekoratörün modülü</td>
    </tr>
    <tr>
      <td>İzleme kolaylığı</td>
      <td>Yüksek</td>
      <td>Daha düşük</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/python-dekoratorlerinde-kimlik-57.svg" alt="python-dekoratorlerinde-kimlik-57" /></p>

<h2 id="functoolswraps-kurtarmaya-geliyor">functools.wraps kurtarmaya geliyor</h2>

<p>Çözüm, iç fonksiyonun üzerine <code class="language-plaintext highlighter-rouge">@wraps(func)</code> eklemektir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">time</span>
<span class="kn">from</span> <span class="n">functools</span> <span class="kn">import</span> <span class="n">wraps</span>

<span class="k">def</span> <span class="nf">zaman_olc</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
    <span class="nd">@wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
    <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="n">baslangic</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="nf">perf_counter</span><span class="p">()</span>
        <span class="n">sonuc</span> <span class="o">=</span> <span class="nf">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
        <span class="n">sure</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="nf">perf_counter</span><span class="p">()</span> <span class="o">-</span> <span class="n">baslangic</span>
        <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Çalışma süresi: </span><span class="si">{</span><span class="n">sure</span><span class="si">:</span><span class="p">.</span><span class="mi">6</span><span class="n">f</span><span class="si">}</span><span class="s"> saniye</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">sonuc</span>

    <span class="k">return</span> <span class="n">wrapper</span>

<span class="nd">@zaman_olc</span>
<span class="k">def</span> <span class="nf">topla</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="sh">"""</span><span class="s">İki sayıyı toplar.</span><span class="sh">"""</span>
    <span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>

<span class="nf">print</span><span class="p">(</span><span class="n">topla</span><span class="p">.</span><span class="n">__name__</span><span class="p">)</span>  <span class="c1"># topla
</span><span class="nf">print</span><span class="p">(</span><span class="n">topla</span><span class="p">.</span><span class="n">__doc__</span><span class="p">)</span>   <span class="c1"># İki sayıyı toplar.
</span></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">wraps</code>, kendi başına sihirli bir kopyalama motoru değildir; <code class="language-plaintext highlighter-rouge">functools.update_wrapper</code> fonksiyonunun dekoratör biçiminde kullanılmasını sağlar. Varsayılan olarak <code class="language-plaintext highlighter-rouge">__module__</code>, <code class="language-plaintext highlighter-rouge">__name__</code>, <code class="language-plaintext highlighter-rouge">__qualname__</code>, <code class="language-plaintext highlighter-rouge">__doc__</code>, <code class="language-plaintext highlighter-rouge">__annotations__</code> ve <code class="language-plaintext highlighter-rouge">__type_params__</code> gibi nitelikleri wrapper’a aktarır. Ayrıca wrapper’ın sözlüğünü günceller.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th style="text-align: right">İsim korunur mu?</th>
      <th style="text-align: right">Docstring korunur mu?</th>
      <th style="text-align: right">Orijinale erişim</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Düz <code class="language-plaintext highlighter-rouge">wrapper</code></td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Closure üzerinden</td>
    </tr>
    <tr>
      <td>Elle kopyalama</td>
      <td style="text-align: right">Kısmen</td>
      <td style="text-align: right">Kısmen</td>
      <td style="text-align: right">Genellikle hayır</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">@wraps(func)</code></td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right"><code class="language-plaintext highlighter-rouge">__wrapped__</code> ile</td>
    </tr>
  </tbody>
</table>

<h2 id="bonus-__wrapped__-ve-introspection">Bonus: <code class="language-plaintext highlighter-rouge">__wrapped__</code> ve introspection</h2>

<p><code class="language-plaintext highlighter-rouge">wraps</code>, wrapper’a <code class="language-plaintext highlighter-rouge">__wrapped__</code> niteliğini de ekler. Böylece orijinal fonksiyona doğrudan ulaşılabilir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">print</span><span class="p">(</span><span class="n">topla</span><span class="p">.</span><span class="nf">__wrapped__</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="c1"># 7; zaman ölçümü yapılmaz
</span></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">inspect.signature</code> gibi introspection araçları da bu zinciri takip ederek anlamlı sonuçlar üretir:</p>

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

<span class="nf">print</span><span class="p">(</span><span class="nf">signature</span><span class="p">(</span><span class="n">topla</span><span class="p">))</span>  <span class="c1"># (a, b)
</span></code></pre></div></div>

<p>Bu özellik yalnızca kozmetik değildir. IDE desteği, otomatik API dokümantasyonu, bağımlılık enjeksiyonu ve test araçları doğru metadata’ya güvenir. Özetle dekoratör yazarken <code class="language-plaintext highlighter-rouge">@wraps(func)</code> kullanmak, emniyet kemeri takmak gibidir: Kod onsuz da ilerleyebilir, fakat ilk sert virajda neden gerekli olduğunu anlarsınız.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="python" /><category term="dekoratör" /><category term="functools" /><category term="metadata" /><category term="wraps" /><summary type="html"><![CDATA[Python dekoratörleri, bir fonksiyonun davranışını kaynak kodunu değiştirmeden genişletmenin zarif bir yoludur. Ancak dekoratörümüzü dikkatsizce yazarsak orijinal fonksiyonun adı, docstring’i ve diğer metadata bilgileri ortadan kaybolabilir. Fonksiyon çalışmaya devam eder ama sahneye başka birinin kimliğiyle çıkar. Neyse ki functools.wraps, bu küçük kimlik krizini çözmek için standart kütüphanede bizi bekler.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/python-dekoratorlerinde-kimlik-57.png" /><media:content medium="image" url="https://program.sonsuz.us/img/python-dekoratorlerinde-kimlik-57.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Robotik Enkoderlerde Konum Hafızası: Mutlak ve Artımlı Enkoderler</title><link href="https://program.sonsuz.us/posts/robotik-enkoderlerde-konum-hafizasi-mutlak-ve-artimli-enkoderler/" rel="alternate" type="text/html" title="Robotik Enkoderlerde Konum Hafızası: Mutlak ve Artımlı Enkoderler" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/robotik-enkoderlerde-konum-hafizasi-mutlak-ve-artimli-enkoderler</id><content type="html" xml:base="https://program.sonsuz.us/posts/robotik-enkoderlerde-konum-hafizasi-mutlak-ve-artimli-enkoderler/"><![CDATA[<p><img src="/img/robotik-enkoderlerde-konum-72.svg" alt="robotik-enkoderlerde-konum-72" /></p>

<p>Bir robot kolunun elektrik kesildikten sonra eklemlerinin nerede olduğunu hâlâ bilmesi sihir değildir; doğru enkoder seçimidir. Motor milinin veya mekanik bir eksenin açısal konumunu ölçen enkoderler, hareket kontrol sistemlerinin gözü gibidir. Ancak mutlak (absolute) ve artımlı (incremental) enkoderler konumu aynı biçimde anlatmaz: biri doğrudan adres verirken diğeri atılan adımları sayar.
``</p>
<h2 id="enkoder-neyi-ölçer">Enkoder neyi ölçer?</h2>

<p>Döner enkoder, mil hareketini elektriksel sinyallere dönüştürür. Ölçülen temel büyüklük açısal konumdur. Bir tam tur $360^\circ$ veya $2\pi$ radyan olduğuna göre, tur başına $N$ farklı konum üreten bir enkoderin teorik çözünürlüğü şöyledir:</p>

\[\Delta\theta = \frac{360^\circ}{N}\]

<p>Örneğin 1024 konumlu bir enkoder için çözünürlük yaklaşık $0{,}3516^\circ$ olur. Fakat “kaç farklı konum ölçülüyor?” sorusu kadar, “bu konum bilgisi nasıl saklanıyor?” sorusu da önemlidir.</p>

<h2 id="artımlı-enkoder-hareketin-muhasebecisi">Artımlı enkoder: Hareketin muhasebecisi</h2>

<p>Artımlı enkoder, mil döndükçe A ve B kanallarında darbeler üretir. Denetleyici bu darbeleri sayarak başlangıç noktasına göre bağıl konumu hesaplar:</p>

\[\theta = \theta_0 + \frac{C}{P}\times360^\circ\]

<p>Burada $C$ sayılan darbe miktarı, $P$ ise kullanılan sayım yöntemine göre bir turdaki toplam sayımdır. A ve B sinyalleri arasında faz farkı bulunduğundan dönüş yönü de anlaşılır. Bazı modellerdeki Z kanalı ise her turda bir kez referans darbesi verir.</p>

<p>Önemli nokta şudur: Artımlı enkoder kendi başına “mil 127 derecede” demez. Yalnızca “başlangıçtan beri şu kadar ilerledim” der. Güç kesildiğinde denetleyicideki sayaç kaybolursa konum bilgisi de kaybolabilir. Bu nedenle açılışta limit anahtarına ilerleme veya Z darbesini arama gibi bir homing işlemi gerekir.</p>

<h2 id="mutlak-enkoder-her-konumun-kimliği-vardır">Mutlak enkoder: Her konumun kimliği vardır</h2>

<p>Mutlak enkoderde her mekanik konuma özgü bir dijital kod atanır. Mil dururken veya sistem yeniden açıldığında kod okunarak konum doğrudan belirlenebilir. Bu yaklaşım, apartman merdivenlerini saymak yerine kapının üzerindeki numaraya bakmaya benzer.</p>

<p>Tek turlu modeller bir tur içindeki açıyı bildirir. Çok turlu modeller ise hem tur içi açıyı hem de tamamlanan tur sayısını korur. Haberleşme SSI, BiSS-C, CANopen veya EtherCAT gibi arayüzlerle gerçekleştirilebilir. Kodlama sırasında geçiş hatalarını azaltmak için sıklıkla Gray kodu kullanılır; komşu iki konum arasında yalnızca bir bit değişir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Artımlı enkoder</th>
      <th>Mutlak enkoder</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Konum türü</td>
      <td>Başlangıca göre bağıl</td>
      <td>Doğrudan ve benzersiz</td>
    </tr>
    <tr>
      <td>Güç sonrası konum</td>
      <td>Genellikle kaybolur</td>
      <td>Yeniden okunabilir</td>
    </tr>
    <tr>
      <td>Homing ihtiyacı</td>
      <td>Çoğunlukla vardır</td>
      <td>Çoğunlukla yoktur</td>
    </tr>
    <tr>
      <td>Çıkış</td>
      <td>A/B/Z darbeleri</td>
      <td>Dijital konum kelimesi</td>
    </tr>
    <tr>
      <td>Maliyet</td>
      <td>Daha düşük</td>
      <td>Daha yüksek</td>
    </tr>
    <tr>
      <td>Tipik kullanım</td>
      <td>Hız kontrolü, konveyör</td>
      <td>Robot kolu, güvenli eksen</td>
    </tr>
  </tbody>
</table>

<h2 id="küçük-bir-artımlı-sayıcı-örneği">Küçük bir artımlı sayıcı örneği</h2>

<p>Aşağıdaki Python kodu, dört kat kenar sayımıyla elde edilen sayacı açıya dönüştürür. Gerçek sistemlerde sayaç, mikrodenetleyicinin kesme veya donanımsal encoder birimiyle güncellenir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PPR</span> <span class="o">=</span> <span class="mi">1024</span>
<span class="n">quadrature_factor</span> <span class="o">=</span> <span class="mi">4</span>
<span class="n">counts_per_rev</span> <span class="o">=</span> <span class="n">PPR</span> <span class="o">*</span> <span class="n">quadrature_factor</span>

<span class="k">def</span> <span class="nf">position_deg</span><span class="p">(</span><span class="n">counter</span><span class="p">):</span>
    <span class="n">normalized</span> <span class="o">=</span> <span class="n">counter</span> <span class="o">%</span> <span class="n">counts_per_rev</span>
    <span class="k">return</span> <span class="n">normalized</span> <span class="o">*</span> <span class="mf">360.0</span> <span class="o">/</span> <span class="n">counts_per_rev</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">position_deg</span><span class="p">(</span><span class="mi">1536</span><span class="p">))</span>  <span class="c1"># 135 derece
</span></code></pre></div></div>

<p>Kod yalnızca sayacı yorumlar; başlangıç referansını kendiliğinden keşfetmez. Sayaç yanlış başlatılırsa hesaplanan açı da aynı miktarda kayar. Mutlak enkoderde ise okunan sayısal değer, uygun ölçekleme ile doğrudan açıya çevrilir.</p>

<h2 id="hangisi-seçilmeli">Hangisi seçilmeli?</h2>

<p>Elektrik kesintisinden sonra eksenin hareket ettirilmeden bilinmesi gerekiyorsa mutlak enkoder güçlü adaydır. Maliyet kritikse, açılışta referanslama yapılabiliyorsa veya temel hedef hız ölçmekse artımlı enkoder yeterli olabilir. Robotik uygulamalarda karar yalnız çözünürlüğe göre verilmemelidir; güvenlik, kablolama, haberleşme gecikmesi, maksimum hız ve homing süresi de değerlendirilmelidir. Kısacası artımlı enkoder yolculuğu sayar, mutlak enkoder ise bulunduğu adresi bilir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="enkoder" /><category term="otomasyon" /><category term="konum-kontrolü" /><category term="sensörler" /><category term="gömülü-sistemler" /><summary type="html"><![CDATA[Bir robot kolunun elektrik kesildikten sonra eklemlerinin nerede olduğunu hâlâ bilmesi sihir değildir; doğru enkoder seçimidir. Motor milinin veya mekanik bir eksenin açısal konumunu ölçen enkoderler, hareket kontrol sistemlerinin gözü gibidir. Ancak mutlak (absolute) ve artımlı (incremental) enkoderler konumu aynı biçimde anlatmaz: biri doğrudan adres verirken diğeri atılan adımları sayar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/robotik-enkoderlerde-konum-72.png" /><media:content medium="image" url="https://program.sonsuz.us/img/robotik-enkoderlerde-konum-72.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Robotik Sinir Ağı Kontrolünde Kararlılık: Zeki Ama Garantisi Nerede?</title><link href="https://program.sonsuz.us/posts/robotik-sinir-agi-kontrolunde-kararlilik-zeki-ama-garantisi-nerede/" rel="alternate" type="text/html" title="Robotik Sinir Ağı Kontrolünde Kararlılık: Zeki Ama Garantisi Nerede?" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/robotik-sinir-agi-kontrolunde-kararlilik-zeki-ama-garantisi-nerede</id><content type="html" xml:base="https://program.sonsuz.us/posts/robotik-sinir-agi-kontrolunde-kararlilik-zeki-ama-garantisi-nerede/"><![CDATA[<p>Bir robot kolunun sinir ağıyla kusursuz biçimde bardak taşıdığını düşünün. Etkileyici, değil mi? Peki kol daha ağır bir bardakla, eğitilmediği bir açıyla veya gürültülü sensörlerle karşılaşırsa ne olur? Yapay sinir ağı tabanlı kontrolcüler yüksek performans gösterebilse de klasik kontrol teorisinin sevdiği türden matematiksel kararlılık garantilerini çoğu zaman beraberinde getirmez.</p>

<p>``</p>

<h2 id="kararlılık-neden-bu-kadar-önemli">Kararlılık neden bu kadar önemli?</h2>

<p>Bir dinamik sistemi genel olarak</p>

\[\dot{x}=f(x,u)\]

<p>şeklinde ifade edebiliriz. Burada $x$ sistemin durumu, $u$ ise kontrol girişidir. Kontrolcünün görevi, örneğin robotun eklem açılarını hedeflenen denge noktasına taşımaktır.</p>

<p>Klasik yaklaşımda $u=K(x)$ seçilir ve kapalı çevrim sisteminin davranışı matematiksel olarak incelenir. Lyapunov teorisi bunun en güçlü araçlarından biridir. Pozitif tanımlı bir $V(x)$ fonksiyonu için</p>

\[V(x)&gt;0, \qquad \dot{V}(x)&lt;0\]

<p>koşulları sağlanıyorsa sistemin denge noktasına doğru ilerlediği gösterilebilir. Başka bir ifadeyle enerji benzeri bir değer sürekli azalır. Robot, matematiksel bir yokuştan aşağı yuvarlanarak hedefe yaklaşır.</p>

<p>Sinir ağı kontrolcüsünde ise giriş genellikle</p>

\[u=\pi_\theta(x)\]

<p>biçimindedir. Çok katmanlı ve doğrusal olmayan $\pi_\theta$ fonksiyonu, milyonlarca parametre içerebilir. Bu nedenle tüm durum uzayında $\dot{V}(x)&lt;0$ olduğunu kanıtlamak oldukça zordur.</p>

<h2 id="klasik-ve-öğrenen-kontrolcü-karşılaştırması">Klasik ve öğrenen kontrolcü karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Klasik kontrol</th>
      <th>Sinir ağı tabanlı kontrol</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Model ihtiyacı</td>
      <td>Genellikle açık model gerekir</td>
      <td>Veriden öğrenebilir</td>
    </tr>
    <tr>
      <td>Kararlılık analizi</td>
      <td>Lyapunov, kutup ve frekans yöntemleri güçlüdür</td>
      <td>Ağın karmaşıklığı analizi zorlaştırır</td>
    </tr>
    <tr>
      <td>Genelleme</td>
      <td>Tasarım bölgesiyle sınırlıdır</td>
      <td>Eğitim dışı durumlarda belirsizdir</td>
    </tr>
    <tr>
      <td>Açıklanabilirlik</td>
      <td>Görece yüksektir</td>
      <td>Çoğu zaman kara kutudur</td>
    </tr>
    <tr>
      <td>Performans</td>
      <td>Karmaşık görevlerde sınırlanabilir</td>
      <td>Yüksek boyutlu görevlerde başarılı olabilir</td>
    </tr>
  </tbody>
</table>

<p>Buradaki temel sorun sinir ağlarının mutlaka kararsız olması değildir. Sorun, eğitim başarısının kanıt anlamına gelmemesidir. Bir kontrolcünün milyonlarca simülasyonda hata yapmaması, henüz denenmemiş bir durumda güvenli kalacağını garanti etmez. Özellikle dağılım kayması, sensör arızası, model belirsizliği ve dış bozucular robotu eğitim verisinin dışına taşıyabilir.</p>

<h2 id="simülasyon-testi-neden-yeterli-değildir">Simülasyon testi neden yeterli değildir?</h2>

<p>Aşağıdaki basit Python kodu, öğrenilmiş bir kontrolcüyü farklı başlangıç durumlarında deneyerek son durum normunu ölçer:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="k">def</span> <span class="nf">controller</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
    <span class="c1"># Gerçekte burada eğitilmiş sinir ağı çalıştırılır.
</span>    <span class="k">return</span> <span class="o">-</span><span class="mf">1.8</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="mf">0.15</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="nf">tanh</span><span class="p">(</span><span class="mi">4</span> <span class="o">*</span> <span class="n">x</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">simulate</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">dt</span><span class="o">=</span><span class="mf">0.01</span><span class="p">,</span> <span class="n">steps</span><span class="o">=</span><span class="mi">1000</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">steps</span><span class="p">):</span>
        <span class="n">u</span> <span class="o">=</span> <span class="nf">controller</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
        <span class="n">x</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">dt</span> <span class="o">*</span> <span class="p">(</span><span class="o">-</span><span class="mf">0.4</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="n">u</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">x</span>

<span class="k">for</span> <span class="n">x0</span> <span class="ow">in</span> <span class="n">np</span><span class="p">.</span><span class="nf">linspace</span><span class="p">(</span><span class="o">-</span><span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">21</span><span class="p">):</span>
    <span class="n">final_state</span> <span class="o">=</span> <span class="nf">simulate</span><span class="p">(</span><span class="n">x0</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="n">x0</span><span class="p">,</span> <span class="nf">abs</span><span class="p">(</span><span class="n">final_state</span><span class="p">))</span>
</code></pre></div></div>

<p>Bu deney faydalıdır; çünkü başarısız başlangıç bölgelerini ortaya çıkarabilir. Ancak yalnızca 21 nokta test edilir. Sürekli durum uzayında sonsuz sayıda olasılık bulunduğundan, başarılı sonuçlar biçimsel bir ispat oluşturmaz. Test güven verir, kanıt ise sınırları tanımlar.</p>

<h2 id="garantiyi-güçlendiren-yaklaşımlar">Garantiyi güçlendiren yaklaşımlar</h2>

<p>Araştırmacılar bu açığı kapatmak için birkaç yöntemi birlikte kullanıyor:</p>

<ul>
  <li><strong>Lyapunov tabanlı öğrenme:</strong> Ağ, yalnızca görev ödülünü değil, $\dot{V}(x)&lt;0$ koşulunu da dikkate alarak eğitilir.</li>
  <li><strong>Control Barrier Function:</strong> Kontrol girişleri güvenli durum kümesinde kalacak şekilde filtrelenir.</li>
  <li><strong>Hibrit mimari:</strong> Sinir ağı yüksek performanslı komut üretirken klasik kontrolcü güvenlik katmanı olarak çalışır.</li>
  <li><strong>Doğrulama araçları:</strong> Aralık analizi, erişilebilirlik analizi ve karma tamsayılı programlama ile ağın belirli bölgelerdeki çıktıları sınırlandırılır.</li>
  <li><strong>Gürbüzlük analizi:</strong> Bozucular altında durumun sınırlı kaldığını göstermek için input-to-state stability gibi kavramlardan yararlanılır.</li>
</ul>

<p>Pratikte en güvenli yaklaşım, sinir ağını tek başına direksiyona oturtmak yerine ona matematik bilen bir yardımcı pilot vermektir. Öğrenen kontrolcü çeviklik ve uyarlanabilirlik sağlarken klasik katman fiziksel sınırları, tork kısıtlarını ve güvenli çalışma bölgesini korur.</p>

<p>Sonuç olarak robotikte başarı ölçütü yalnızca görevi tamamlamak değildir. Kontrolcünün hangi koşullarda güvenli olduğunu bilmek de gerekir. Sinir ağları güçlü sürücülerdir; fakat kararlılık kanıtı olmadan emniyet kemerleri henüz tam bağlanmış sayılmaz.</p>

<p><img src="/img/robotik-sinir-agi-70.svg" alt="robotik-sinir-agi-70" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="yapay sinir ağları" /><category term="kontrol teorisi" /><category term="kararlılık" /><category term="lyapunov" /><category term="makine öğrenmesi" /><summary type="html"><![CDATA[Bir robot kolunun sinir ağıyla kusursuz biçimde bardak taşıdığını düşünün. Etkileyici, değil mi? Peki kol daha ağır bir bardakla, eğitilmediği bir açıyla veya gürültülü sensörlerle karşılaşırsa ne olur? Yapay sinir ağı tabanlı kontrolcüler yüksek performans gösterebilse de klasik kontrol teorisinin sevdiği türden matematiksel kararlılık garantilerini çoğu zaman beraberinde getirmez.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/robotik-sinir-agi-70.png" /><media:content medium="image" url="https://program.sonsuz.us/img/robotik-sinir-agi-70.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Robotlarda Sensör Kalibrasyonu Neden Zamanla Kayar?</title><link href="https://program.sonsuz.us/posts/robotlarda-sensor-kalibrasyonu-neden-zamanla-kayar/" rel="alternate" type="text/html" title="Robotlarda Sensör Kalibrasyonu Neden Zamanla Kayar?" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/robotlarda-sensor-kalibrasyonu-neden-zamanla-kayar</id><content type="html" xml:base="https://program.sonsuz.us/posts/robotlarda-sensor-kalibrasyonu-neden-zamanla-kayar/"><![CDATA[<p><img src="/img/robotlarda-sensor-kalibrasyonu-26.svg" alt="robotlarda-sensor-kalibrasyonu-26" /></p>

<p>Bir robot fabrikadan kusursuz kalibre edilmiş biçimde çıksa bile bu durum sonsuza kadar sürmez. Kamera, LiDAR, IMU, enkoder ve GPS gibi sensörlerin ölçümleri; sıcaklık, titreşim, mekanik aşınma ve elektronik yaşlanma nedeniyle zamanla birbirinden uzaklaşır. Robot hâlâ veri topluyor gibi görünür, ancak artık dünyayı hafifçe “yamuk” algılıyordur. İşte bu yavaş bozulmaya kalibrasyon kayması, yani <strong>drift</strong> denir.</p>

<p>``</p>

<h2 id="çoklu-sensör-kalibrasyonu-nedir">Çoklu sensör kalibrasyonu nedir?</h2>

<p>Çoklu sensörlü bir sistemde yalnızca her sensörün kendi doğruluğu değil, sensörlerin birbirleriyle olan geometrik ve zamansal ilişkileri de önemlidir. Örneğin kamera ile LiDAR arasındaki dönüşüm genellikle şu katı cisim dönüşümüyle gösterilir:</p>

\[\mathbf{p}_{kamera} = \mathbf{R}\mathbf{p}_{lidar} + \mathbf{t}\]

<p>Burada $\mathbf{R}$ dönme matrisini, $\mathbf{t}$ ise öteleme vektörünü temsil eder. Sensör yuvasının bir vida kadar oynaması bile bu dış parametreleri değiştirir. Benzer şekilde kameranın odak uzaklığı veya mercek bozulması gibi iç parametreler de sıcaklık ve darbe etkisiyle sapabilir.</p>

<p>Zamansal kalibrasyon da en az geometrik kalibrasyon kadar kritiktir. Kamera görüntüsü ile IMU ölçümü arasında $\Delta t$ gecikmesi varsa hızlı hareket sırasında aynı fiziksel an karşılaştırılmaz. Açısal hız $\omega$ olduğunda yaklaşık yönelim hatası şöyle büyür:</p>

\[\Delta \theta \approx \omega \Delta t\]

<p>Robot hızlandıkça küçücük bir saat farkının büyük konum hatasına dönüşmesinin nedeni budur.</p>

<h2 id="drift-neden-oluşur">Drift neden oluşur?</h2>

<table>
  <thead>
    <tr>
      <th>Drift kaynağı</th>
      <th>Etkilenen bileşen</th>
      <th>Olası belirti</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sıcaklık değişimi</td>
      <td>IMU biası, kamera odağı</td>
      <td>Konumun yavaşça sürüklenmesi</td>
    </tr>
    <tr>
      <td>Titreşim ve darbe</td>
      <td>Sensörün dış dönüşümü</td>
      <td>Nokta bulutunun görüntüyle örtüşmemesi</td>
    </tr>
    <tr>
      <td>Mekanik aşınma</td>
      <td>Enkoder, mafsal geometrisi</td>
      <td>Tekrarlanan hareketlerde farklı sonuç</td>
    </tr>
    <tr>
      <td>Saat kayması</td>
      <td>Sensör zaman damgaları</td>
      <td>Hızlı dönüşlerde çift kenarlar</td>
    </tr>
    <tr>
      <td>Elektronik yaşlanma</td>
      <td>Kazanç ve ofset</td>
      <td>Sistematik ölçüm sapması</td>
    </tr>
    <tr>
      <td>Yazılım güncellemesi</td>
      <td>Sürücü ve koordinat sistemi</td>
      <td>Güncelleme sonrası ani uyumsuzluk</td>
    </tr>
  </tbody>
</table>

<p>Drift her zaman doğrusal ilerlemez. Robot soğukken farklı, çalışma sıcaklığına ulaştığında farklı davranabilir. Bu nedenle yalnızca “ayda bir kalibre et” yaklaşımı her sistem için yeterli değildir.</p>

<h2 id="yeniden-kalibrasyon-zamanı-nasıl-anlaşılır">Yeniden kalibrasyon zamanı nasıl anlaşılır?</h2>

<p>Kalibrasyon sağlığı, sensörlerin ortak gözlemleri arasındaki <strong>residual</strong>, yani artık hata üzerinden izlenebilir. Ölçülen değer $z_i$, modelin tahmini $h_i(\mathbf{x})$ ise toplam hata:</p>

\[J(\mathbf{x}) = \sum_i \left\\vert z_i-h_i(\mathbf{x})\right\\vert _{\Sigma_i^{-1}}^2\]

<p>şeklinde tanımlanabilir. $J$ değerinin sürekli yükselmesi, sensör ilişkisinin bozulduğuna işaret eder. Ancak hareketli nesneler, yağmur veya kirli mercek de residual değerini artırabileceğinden tek ölçümle karar verilmemelidir.</p>

<p>Aşağıdaki Python örneği, hata serisinin hareketli ortalamasını izleyerek basit bir yeniden kalibrasyon uyarısı üretir:</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">deque</span>

<span class="k">class</span> <span class="nc">CalibrationMonitor</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">window</span><span class="o">=</span><span class="mi">30</span><span class="p">,</span> <span class="n">threshold</span><span class="o">=</span><span class="mf">1.5</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">errors</span> <span class="o">=</span> <span class="nf">deque</span><span class="p">(</span><span class="n">maxlen</span><span class="o">=</span><span class="n">window</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="n">threshold</span> <span class="o">=</span> <span class="n">threshold</span>

    <span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">residual</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">errors</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">residual</span><span class="p">)</span>
        <span class="k">if</span> <span class="nf">len</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="n">errors</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">self</span><span class="p">.</span><span class="n">errors</span><span class="p">.</span><span class="n">maxlen</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>

        <span class="n">mean_error</span> <span class="o">=</span> <span class="nf">sum</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="n">errors</span><span class="p">)</span> <span class="o">/</span> <span class="nf">len</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="n">errors</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">mean_error</span> <span class="o">&gt;</span> <span class="n">self</span><span class="p">.</span><span class="n">threshold</span>

<span class="n">monitor</span> <span class="o">=</span> <span class="nc">CalibrationMonitor</span><span class="p">(</span><span class="n">window</span><span class="o">=</span><span class="mi">30</span><span class="p">,</span> <span class="n">threshold</span><span class="o">=</span><span class="mf">1.5</span><span class="p">)</span>

<span class="k">for</span> <span class="n">error</span> <span class="ow">in</span> <span class="p">[</span><span class="mf">0.8</span><span class="p">]</span> <span class="o">*</span> <span class="mi">20</span> <span class="o">+</span> <span class="p">[</span><span class="mf">1.9</span><span class="p">]</span> <span class="o">*</span> <span class="mi">30</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">monitor</span><span class="p">.</span><span class="nf">update</span><span class="p">(</span><span class="n">error</span><span class="p">):</span>
        <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Yeniden kalibrasyon öneriliyor!</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">break</span>
</code></pre></div></div>

<p>Bu kod ani bir sıçrama yerine son 30 ölçümün ortalamasını kullanır. Gerçek sistemlerde sıcaklık, robot hızı ve titreşim seviyesi de karara eklenerek yanlış alarmlar azaltılabilir.</p>

<h2 id="takvim-mi-koşul-bazlı-bakım-mı">Takvim mi, koşul bazlı bakım mı?</h2>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Periyodik kalibrasyon</td>
      <td>Planlaması kolaydır</td>
      <td>Gereksiz bakım yapılabilir</td>
    </tr>
    <tr>
      <td>Koşul bazlı kalibrasyon</td>
      <td>Gerçek bozulmaya tepki verir</td>
      <td>İzleme altyapısı gerektirir</td>
    </tr>
    <tr>
      <td>Sürekli çevrim içi kalibrasyon</td>
      <td>Drift hareket sırasında düzeltilir</td>
      <td>Gözlemlenebilirlik ve hesaplama zordur</td>
    </tr>
    <tr>
      <td>Hibrit yaklaşım</td>
      <td>Güvenlik ile verimliliği dengeler</td>
      <td>Tasarımı daha karmaşıktır</td>
    </tr>
  </tbody>
</table>

<p>Güvenlik kritik robotlarda en sağlam çözüm genellikle hibrittir: residual değerleri sürekli izlenir, eşik aşılırsa erken bakım yapılır ve buna rağmen belirli aralıklarla doğrulama kalibrasyonu uygulanır. Ayrıca kalibrasyon parametreleri sıcaklıkla birlikte kaydedilmeli, sensör montajları işaretlenmeli ve her bakım sonrası referans veri setiyle test edilmelidir.</p>

<p>Sonuç olarak kalibrasyon tek seferlik bir kurulum adımı değil, robotun yaşam döngüsü boyunca yönetilmesi gereken bir sağlık göstergesidir. Robotun dünyayı doğru görmesini istiyorsak yalnızca sensörlerin çalışıp çalışmadığını değil, hâlâ aynı dünyaya bakıp bakmadıklarını da sorgulamalıyız.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="sensör füzyonu" /><category term="kalibrasyon" /><category term="drift" /><category term="python" /><category term="otonom sistemler" /><summary type="html"><![CDATA[Bir robot fabrikadan kusursuz kalibre edilmiş biçimde çıksa bile bu durum sonsuza kadar sürmez. Kamera, LiDAR, IMU, enkoder ve GPS gibi sensörlerin ölçümleri; sıcaklık, titreşim, mekanik aşınma ve elektronik yaşlanma nedeniyle zamanla birbirinden uzaklaşır. Robot hâlâ veri topluyor gibi görünür, ancak artık dünyayı hafifçe “yamuk” algılıyordur. İşte bu yavaş bozulmaya kalibrasyon kayması, yani drift denir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/robotlarda-sensor-kalibrasyonu-26.png" /><media:content medium="image" url="https://program.sonsuz.us/img/robotlarda-sensor-kalibrasyonu-26.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">sudo Ortam Değişkenlerini Neden Kaybeder?</title><link href="https://program.sonsuz.us/posts/sudo-ortam-degiskenlerini-neden-kaybeder/" rel="alternate" type="text/html" title="sudo Ortam Değişkenlerini Neden Kaybeder?" /><published>2026-10-21T00:00:00+00:00</published><updated>2026-10-21T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/sudo-ortam-degiskenlerini-neden-kaybeder</id><content type="html" xml:base="https://program.sonsuz.us/posts/sudo-ortam-degiskenlerini-neden-kaybeder/"><![CDATA[<p>Terminalde çalışan bir komutun başına <code class="language-plaintext highlighter-rouge">sudo</code> eklediğinizde aniden API anahtarını, özel <code class="language-plaintext highlighter-rouge">PATH</code> ayarını veya uygulama yapılandırmasını görememesi oldukça şaşırtıcıdır. Fakat bu davranış bir hata değil, <code class="language-plaintext highlighter-rouge">sudo</code> tarafından bilinçli şekilde uygulanan bir güvenlik önlemidir. Gelin değişkenlerin nereye kaybolduğunu ve onları güvenli biçimde nasıl geri getirebileceğimizi inceleyelim.</p>

<p>``</p>

<h2 id="ortam-değişkeni-nedir">Ortam değişkeni nedir?</h2>

<p>Shell, başlattığı süreçlere anahtar-değer çiftlerinden oluşan bir ortam aktarır. Örneğin aşağıdaki komut, <code class="language-plaintext highlighter-rouge">APP_MODE</code> değişkenini mevcut shell ve onun alt süreçleri için erişilebilir yapar:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">APP_MODE</span><span class="o">=</span>development
node app.js
</code></pre></div></div>

<p>Normal koşullarda çocuk süreç, ebeveyn sürecin dışa aktarılmış değişkenlerinin bir kopyasını alır. Bunu basitleştirerek şu şekilde ifade edebiliriz:</p>

\[E_{child} = E_{parent} \cup E_{command}\]

<p>Burada $E$, sürece aktarılan ortam değişkenleri kümesidir. Ancak araya <code class="language-plaintext highlighter-rouge">sudo</code> girdiğinde yeni süreç yalnızca shell tarafından değil, ayrıca <code class="language-plaintext highlighter-rouge">sudo</code> güvenlik politikası tarafından hazırlanır:</p>

\[E_{sudo} = (E_{parent} \cap E_{allowed}) \cup E_{sudo\_defaults}\]

<p>Yani yalnızca izin verilen değişkenler korunur; geri kalanı temizlenir veya güvenli varsayılanlarla değiştirilir.</p>

<h2 id="neden-temizleniyor">Neden temizleniyor?</h2>

<p>Bir ortam değişkeni masum görünse de çalıştırılacak kodu etkileyebilir. <code class="language-plaintext highlighter-rouge">PATH</code>, <code class="language-plaintext highlighter-rouge">LD_PRELOAD</code>, <code class="language-plaintext highlighter-rouge">PYTHONPATH</code> ve benzeri değişkenler yanlış programın ya da kütüphanenin root yetkisiyle yüklenmesine yol açabilir. Kullanıcının bütün ortamını doğrudan yönetici sürecine taşımak, yetki yükseltme açığı oluşturabilir.</p>

<p>Birçok sistemde <code class="language-plaintext highlighter-rouge">/etc/sudoers</code> içindeki <code class="language-plaintext highlighter-rouge">env_reset</code> seçeneği bu filtrelemeyi etkinleştirir. Ayrıca <code class="language-plaintext highlighter-rouge">secure_path</code>, <code class="language-plaintext highlighter-rouge">sudo</code> ile çalıştırılan komutlarda kullanılacak güvenilir bir <code class="language-plaintext highlighter-rouge">PATH</code> tanımlar.</p>

<table>
  <thead>
    <tr>
      <th>Yöntem</th>
      <th>Değişken davranışı</th>
      <th>Güvenlik durumu</th>
      <th>Kullanım amacı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">sudo komut</code></td>
      <td>Çoğu özel değişken silinir</td>
      <td>En güvenli varsayılan</td>
      <td>Genel yönetim işleri</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">sudo -E komut</code></td>
      <td>İzin verilen kullanıcı ortamı korunur</td>
      <td>Daha dikkatli kullanılmalı</td>
      <td>Geçici geliştirme işlemleri</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">sudo VAR=değer komut</code></td>
      <td>Belirli değişken aktarılır</td>
      <td>Kontrollü</td>
      <td>Tek değişken gereken işler</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">sudoers env_keep</code></td>
      <td>Seçilen değişkenler kalıcı korunur</td>
      <td>Doğru yapılandırılmalı</td>
      <td>Sistem çapında politika</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/sudo-ortam-degiskenlerini-61.svg" alt="sudo-ortam-degiskenlerini-61" /></p>

<h2 id="önce-problemi-doğrulayın">Önce problemi doğrulayın</h2>

<p>Aynı değişkeni normal kullanıcı ve <code class="language-plaintext highlighter-rouge">sudo</code> ortamında karşılaştırabilirsiniz:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">APP_MODE</span><span class="o">=</span>development
<span class="nb">printenv </span>APP_MODE
<span class="nb">sudo printenv </span>APP_MODE
</code></pre></div></div>

<p>İlk komut <code class="language-plaintext highlighter-rouge">development</code> yazarken ikinci komut boş sonuç verebilir. Ortamların tamamını karşılaştırmak için çıktıları sıralayıp <code class="language-plaintext highlighter-rouge">diff</code> kullanmak daha açıklayıcıdır:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">env</span> | <span class="nb">sort</span> <span class="o">&gt;</span> /tmp/user-env.txt
<span class="nb">sudo env</span> | <span class="nb">sort</span> <span class="o">&gt;</span> /tmp/sudo-env.txt
diff <span class="nt">-u</span> /tmp/user-env.txt /tmp/sudo-env.txt
</code></pre></div></div>

<p>Bu kod, iki ortam arasındaki eklenen, kaldırılan veya değiştirilen değerleri gösterir.</p>

<h2 id="güvenli-çözüm-seçenekleri">Güvenli çözüm seçenekleri</h2>

<p>Yalnızca gerekli değişkeni komut satırında geçirmek genellikle en açık çözümdür:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span><span class="nv">APP_MODE</span><span class="o">=</span>production /opt/myapp/start.sh
</code></pre></div></div>

<p>Değişken mevcut shell değerinden alınacaksa şu biçim kullanılabilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span><span class="nv">APP_MODE</span><span class="o">=</span><span class="s2">"</span><span class="nv">$APP_MODE</span><span class="s2">"</span> /opt/myapp/start.sh
</code></pre></div></div>

<p>Tüm ortamı korumayı denemek için <code class="language-plaintext highlighter-rouge">sudo -E</code> kullanılabilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> <span class="nt">-E</span> ./deploy.sh
</code></pre></div></div>

<p>Ancak <code class="language-plaintext highlighter-rouge">-E</code>, sistemdeki <code class="language-plaintext highlighter-rouge">sudoers</code> politikası izin vermiyorsa etkisiz olabilir. Ayrıca hassas veya davranış değiştirici değişkenleri root sürecine taşımak risklidir.</p>

<p>Kalıcı ve kontrollü izin için <code class="language-plaintext highlighter-rouge">sudo visudo</code> ile yapılandırma düzenlenebilir:</p>

<pre><code class="language-sudoers">Defaults env_keep += "APP_MODE API_ENDPOINT"
</code></pre>

<p><code class="language-plaintext highlighter-rouge">visudo</code>, sözdizimini doğrulayarak hatalı bir dosya yüzünden <code class="language-plaintext highlighter-rouge">sudo</code> erişiminin bozulmasını önler. API anahtarlarını bu listeye gelişigüzel eklemek yerine secret manager, korumalı yapılandırma dosyası veya systemd kimlik bilgileri kullanmak daha doğrudur.</p>

<p>Sonuç olarak <code class="language-plaintext highlighter-rouge">sudo</code>, değişkenlerinizi unutmaz; onları güvenlik kontrolünden geçirir. En iyi yaklaşım, bütün ortamı taşımak yerine ihtiyaç duyulan değişkenleri açıkça ve mümkün olan en dar kapsamda aktarmaktır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="linux" /><category term="sudo" /><category term="ortam-değişkenleri" /><category term="shell" /><category term="güvenlik" /><category term="devops" /><summary type="html"><![CDATA[Terminalde çalışan bir komutun başına sudo eklediğinizde aniden API anahtarını, özel PATH ayarını veya uygulama yapılandırmasını görememesi oldukça şaşırtıcıdır. Fakat bu davranış bir hata değil, sudo tarafından bilinçli şekilde uygulanan bir güvenlik önlemidir. Gelin değişkenlerin nereye kaybolduğunu ve onları güvenli biçimde nasıl geri getirebileceğimizi inceleyelim.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/sudo-ortam-degiskenlerini-61.png" /><media:content medium="image" url="https://program.sonsuz.us/img/sudo-ortam-degiskenlerini-61.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>