<?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-09T06:05:58+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">Bağış Toplama Sistemleri Karşılaştırması: CiviCRM, GiveWP ve Open Collective</title><link href="https://program.sonsuz.us/posts/bagis-toplama-sistemleri-karsilastirmasi-civicrm-givewp-ve-open-collective/" rel="alternate" type="text/html" title="Bağış Toplama Sistemleri Karşılaştırması: CiviCRM, GiveWP ve Open Collective" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/bagis-toplama-sistemleri-karsilastirmasi-civicrm-givewp-ve-open-collective</id><content type="html" xml:base="https://program.sonsuz.us/posts/bagis-toplama-sistemleri-karsilastirmasi-civicrm-givewp-ve-open-collective/"><![CDATA[<p>Bir bağış sistemi seçmek, web sitesine yalnızca renkli bir “Destek Ol” düğmesi eklemekten çok daha fazlasıdır. Bağışçı ilişkileri, ödeme altyapısı, kampanya takibi, şeffaflık ve raporlama gibi parçalar doğru biçimde birleşmelidir. CiviCRM, GiveWP ve Open Collective aynı amaca hizmet ediyor gibi görünse de farklı organizasyon modellerine hitap eder: biri kapsamlı bir ilişki yönetim sistemi, biri WordPress odaklı bağış eklentisi, diğeri ise şeffaf topluluk finansmanı platformudur.</p>

<p>``</p>

<h2 id="önce-temel-mantık-bağış-sistemi-nasıl-çalışır">Önce temel mantık: Bağış sistemi nasıl çalışır?</h2>

<p>Tipik bir bağış akışı; bağışçı, form, ödeme sağlayıcısı, işlem kaydı ve raporlama katmanlarından oluşur. Kullanıcı formu doldurduğunda sistem ödeme sağlayıcısına bir istek gönderir. Başarılı işlem sonrasında bağış kaydedilir, makbuz oluşturulur ve gerekiyorsa bağışçıya otomatik e-posta gönderilir.</p>

<p>Bir kampanyanın net geliri basitçe şöyle modellenebilir:</p>

\[G_{net} = G_{brüt} - (G_{brüt} \times o_{komisyon}) - M_{sabit} - G_{iade}\]

<p>Burada $o_{komisyon}$ ödeme sağlayıcısının oransal kesintisini, $M_{sabit}$ işlem başına sabit maliyetleri temsil eder. Dolayısıyla yalnızca yazılımın fiyatını değil, ödeme komisyonlarını ve operasyon yükünü de karşılaştırmak gerekir.</p>

<h2 id="üç-sistemin-karakteri">Üç sistemin karakteri</h2>

<table>
  <thead>
    <tr>
      <th>Sistem</th>
      <th>Temel yaklaşım</th>
      <th>Güçlü olduğu alan</th>
      <th>Teknik ihtiyaç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>CiviCRM</td>
      <td>CRM ve bağış yönetimi</td>
      <td>STK, dernek, üyelik ve etkinlik takibi</td>
      <td>Orta-yüksek</td>
    </tr>
    <tr>
      <td>GiveWP</td>
      <td>WordPress bağış eklentisi</td>
      <td>Hızlı kampanya sayfaları ve formlar</td>
      <td>Orta</td>
    </tr>
    <tr>
      <td>Open Collective</td>
      <td>Şeffaf mali yönetim platformu</td>
      <td>Açık kaynak ve topluluk projeleri</td>
      <td>Düşük-orta</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/bagis-toplama-sistemleri-54.svg" alt="bagis-toplama-sistemleri-54" /></p>

<h3 id="civicrm-kurumsal-hafıza-isteyenlere">CiviCRM: Kurumsal hafıza isteyenlere</h3>

<p>CiviCRM yalnızca ödeme almakla kalmaz; bağışçıları, üyelikleri, etkinlikleri, e-postaları ve geçmiş etkileşimleri tek profilde toplar. Drupal, Joomla veya WordPress ile çalışabilir. Özellikle aynı destekçiyle yıllar boyunca ilişki kuran kuruluşlar için güçlüdür.</p>

<p>Bunun karşılığında kurulum ve bakım daha zahmetlidir. Veri modeli, roller, izinler ve zamanlanmış görevler doğru yapılandırılmalıdır. Küçük bir kampanya için ağır gelebilir; fakat binlerce kişiyle çalışan bir STK için adeta dijital genel merkezdir.</p>

<h3 id="givewp-wordpress-içinde-pratik-çözüm">GiveWP: WordPress içinde pratik çözüm</h3>

<p>GiveWP, mevcut WordPress sitesini bağış platformuna dönüştürür. Kampanya formları, hedef göstergeleri, bağışçı panelleri ve tekrarlayan ödeme özellikleri sunar. İçerik ekibinin WordPress’e aşina olması önemli bir avantajdır.</p>

<p>Basit bir entegrasyon mantığı şu şekilde düşünülebilir:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">add_action</span><span class="p">(</span><span class="s1">'give_insert_payment'</span><span class="p">,</span> <span class="k">function</span> <span class="p">(</span><span class="nv">$payment_id</span><span class="p">)</span> <span class="p">{</span>
    <span class="nv">$amount</span> <span class="o">=</span> <span class="nf">give_get_payment_total</span><span class="p">(</span><span class="nv">$payment_id</span><span class="p">);</span>
    <span class="nb">error_log</span><span class="p">(</span><span class="s1">'Yeni bağış tutarı: '</span> <span class="mf">.</span> <span class="nv">$amount</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>

<p>Bu örnek, yeni ödeme kaydedildiğinde bağış tutarını günlük dosyasına yazar. Gerçek projede aynı kanca CRM bildirimi göndermek veya özel bir teşekkür süreci başlatmak için kullanılabilir. Ancak ücretli eklentiler, ödeme ağ geçitleri ve WordPress güvenliği toplam maliyete eklenmelidir.</p>

<h3 id="open-collective-şeffaflık-varsayılan-ayar">Open Collective: Şeffaflık varsayılan ayar</h3>

<p>Open Collective özellikle açık kaynak projeleri, yerel topluluklar ve gayriresmî gruplar için dikkat çekicidir. Gelirler ve giderler herkese açık gösterilebilir. Bir mali sponsor kullanıldığında topluluk, ayrı bir tüzel kişilik kurmadan para kabul etme ve harcama olanağı bulabilir.</p>

<p>Platformun en güçlü tarafı şeffaflıktır; ancak klasik CRM özellikleri veya tamamen özelleştirilebilir bağış deneyimi bekleyen kuruluşlar için sınırlı kalabilir.</p>

<h2 id="hangisini-seçmeli">Hangisini seçmeli?</h2>

<table>
  <thead>
    <tr>
      <th>İhtiyaç</th>
      <th>Önerilen seçenek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ayrıntılı bağışçı geçmişi ve üyelik yönetimi</td>
      <td>CiviCRM</td>
    </tr>
    <tr>
      <td>WordPress üzerinde hızlı bağış kampanyası</td>
      <td>GiveWP</td>
    </tr>
    <tr>
      <td>Herkese açık gelir-gider takibi</td>
      <td>Open Collective</td>
    </tr>
    <tr>
      <td>İleri düzey özelleştirme ve veri sahipliği</td>
      <td>CiviCRM veya GiveWP</td>
    </tr>
    <tr>
      <td>Minimum altyapı yönetimi</td>
      <td>Open Collective</td>
    </tr>
  </tbody>
</table>

<p>Karar verirken bağış hacmi, ekip kapasitesi, veri gizliliği ve raporlama gereksinimleri birlikte değerlendirilmelidir. Kısacası CiviCRM ilişkiyi, GiveWP dönüşümü, Open Collective ise güveni ve şeffaflığı merkeze koyar. En iyi sistem en fazla özelliğe sahip olan değil, kuruluşunuzun günlük iş akışına en az sürtünmeyle uyum sağlayandır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="bağış" /><category term="civicrm" /><category term="givewp" /><category term="open-collective" /><category term="wordpress" /><category term="açık-kaynak" /><category term="fintech" /><summary type="html"><![CDATA[Bir bağış sistemi seçmek, web sitesine yalnızca renkli bir “Destek Ol” düğmesi eklemekten çok daha fazlasıdır. Bağışçı ilişkileri, ödeme altyapısı, kampanya takibi, şeffaflık ve raporlama gibi parçalar doğru biçimde birleşmelidir. CiviCRM, GiveWP ve Open Collective aynı amaca hizmet ediyor gibi görünse de farklı organizasyon modellerine hitap eder: biri kapsamlı bir ilişki yönetim sistemi, biri WordPress odaklı bağış eklentisi, diğeri ise şeffaf topluluk finansmanı platformudur.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/bagis-toplama-sistemleri-54.png" /><media:content medium="image" url="https://program.sonsuz.us/img/bagis-toplama-sistemleri-54.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Dijital Katılım Platformları: Decidim, CONSUL DEMOCRACY ve FixMyStreet</title><link href="https://program.sonsuz.us/posts/dijital-katilim-platformlari-decidim-consul-democracy-ve-fixmystreet/" rel="alternate" type="text/html" title="Dijital Katılım Platformları: Decidim, CONSUL DEMOCRACY ve FixMyStreet" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/dijital-katilim-platformlari-decidim-consul-democracy-ve-fixmystreet</id><content type="html" xml:base="https://program.sonsuz.us/posts/dijital-katilim-platformlari-decidim-consul-democracy-ve-fixmystreet/"><![CDATA[<p>Bir mahalledeki bozuk kaldırımı bildirmek, belediyeye yeni bir bisiklet yolu önermek veya belirli bir konuda binlerce imza toplamak istiyorsanız sıradan bir formdan fazlasına ihtiyacınız vardır. Decidim, CONSUL DEMOCRACY ve FixMyStreet; vatandaşlarla kurumlar arasında dijital köprü kuran açık kaynaklı platformlardır. Ancak aynı aileden görünseler de farklı problemleri çözerler.</p>

<p>``</p>

<h2 id="üç-platform-üç-yaklaşım">Üç platform, üç yaklaşım</h2>

<p><strong>Decidim</strong>, Barselona çıkışlı kapsamlı bir katılımcı demokrasi altyapısıdır. Teklif oluşturma, destek toplama, toplantı düzenleme, anket, bütçeleme ve sonuç takibi gibi süreçleri modüler biçimde sunar. Bir dilekçe sistemi kurmanın yanında tüm karar alma döngüsünü yönetmek isteyen kurumlara uygundur.</p>

<p><strong>CONSUL DEMOCRACY</strong>, vatandaş önerileri, tartışmalar, oylamalar ve katılımcı bütçeleme üzerine yoğunlaşır. Teklif belirli bir destek eşiğine ulaştığında değerlendirme ya da oylama aşamasına geçirilebilir. Bu nedenle klasik “öneri ver, imza topla, gündeme taşı” modeliyle oldukça uyumludur.</p>

<p><strong>FixMyStreet</strong> ise doğrudan bir dilekçe platformu değildir. Vatandaşların harita üzerinde çukur, kırık sokak lambası veya kaçak döküm gibi yerel sorunları bildirmesini sağlar. Bildirim, konuma göre sorumlu kuruma yönlendirilir ve çözüm durumu kamuya açık şekilde izlenebilir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Decidim</th>
      <th>CONSUL DEMOCRACY</th>
      <th>FixMyStreet</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Temel amaç</td>
      <td>Çok yönlü katılım</td>
      <td>Öneri ve oylama</td>
      <td>Coğrafi sorun bildirimi</td>
    </tr>
    <tr>
      <td>İmza/destek toplama</td>
      <td>Güçlü</td>
      <td>Güçlü</td>
      <td>Doğal özelliği değil</td>
    </tr>
    <tr>
      <td>Harita odaklı çalışma</td>
      <td>Ek modüllerle</td>
      <td>Sınırlı</td>
      <td>Çok güçlü</td>
    </tr>
    <tr>
      <td>Katılımcı bütçe</td>
      <td>Var</td>
      <td>Var</td>
      <td>Yok</td>
    </tr>
    <tr>
      <td>Uygun ölçek</td>
      <td>Kurum ve şehir</td>
      <td>Belediye ve ülke</td>
      <td>Belediye ve mahalle</td>
    </tr>
  </tbody>
</table>

<h2 id="i̇mza-sistemi-nasıl-düşünülmeli">İmza sistemi nasıl düşünülmeli?</h2>

<p>Basit modelde her dilekçenin bir destek sayısı ve hedefi bulunur. İlerleme oranı şöyle hesaplanabilir:</p>

\[P = 100 * S / H\]

<p>Burada $S$ doğrulanmış destek sayısını, $H$ hedeflenen desteği, $P$ ise yüzde ilerlemeyi ifade eder. Örneğin 2.000 destek hedefleyen bir öneri 1.250 doğrulanmış imzaya ulaştığında ilerleme oranı yüzde 62,5 olur.</p>

<p>Fakat yalnızca sayaç tutmak yeterli değildir. Aynı kişinin tekrar imza atması engellenmeli, e-posta veya kimlik doğrulaması yapılmalı ve kişisel veriler gereksiz yere yayımlanmamalıdır. İdeal süreç şu durum makinesini izleyebilir:</p>

<p><code class="language-plaintext highlighter-rouge">Taslak → Moderasyon → Yayında → Eşik Aşıldı → Kurumsal İnceleme → Sonuçlandı</code></p>

<p>Aşağıdaki basitleştirilmiş Python fonksiyonu, doğrulanmış ve benzersiz destekleri sayar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">petition_progress</span><span class="p">(</span><span class="n">signatures</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
    <span class="c1"># Doğrulanmış kullanıcı kimliklerini kümeye alarak tekrarları eler.
</span>    <span class="n">verified_users</span> <span class="o">=</span> <span class="p">{</span>
        <span class="n">item</span><span class="p">[</span><span class="sh">"</span><span class="s">user_id</span><span class="sh">"</span><span class="p">]</span>
        <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">signatures</span>
        <span class="k">if</span> <span class="n">item</span><span class="p">[</span><span class="sh">"</span><span class="s">verified</span><span class="sh">"</span><span class="p">]</span> <span class="ow">is</span> <span class="bp">True</span>
    <span class="p">}</span>

    <span class="n">support_count</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">verified_users</span><span class="p">)</span>
    <span class="n">percentage</span> <span class="o">=</span> <span class="nf">min</span><span class="p">((</span><span class="n">support_count</span> <span class="o">/</span> <span class="n">target</span><span class="p">)</span> <span class="o">*</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>

    <span class="k">return</span> <span class="p">{</span>
        <span class="sh">"</span><span class="s">support_count</span><span class="sh">"</span><span class="p">:</span> <span class="n">support_count</span><span class="p">,</span>
        <span class="sh">"</span><span class="s">percentage</span><span class="sh">"</span><span class="p">:</span> <span class="nf">round</span><span class="p">(</span><span class="n">percentage</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span>
        <span class="sh">"</span><span class="s">threshold_reached</span><span class="sh">"</span><span class="p">:</span> <span class="n">support_count</span> <span class="o">&gt;=</span> <span class="n">target</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>Gerçek sistemde <code class="language-plaintext highlighter-rouge">user_id</code> değerleri herkese açık gösterilmemeli; mümkünse tek yönlü özetler, yetkilendirme katmanları ve kayıt saklama politikaları kullanılmalıdır. Ayrıca kötüye kullanım önleme mekanizması erişilebilirliği bozmamalıdır: aşırı CAPTCHA kullanımı gerçek vatandaşları da kaçırabilir.</p>

<h2 id="hangisini-seçmelisiniz">Hangisini seçmelisiniz?</h2>

<table>
  <thead>
    <tr>
      <th>İhtiyaç</th>
      <th>Önerilen platform</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Dilekçe, toplantı ve bütçe tek yerde olsun</td>
      <td>Decidim</td>
    </tr>
    <tr>
      <td>Öneriler destek eşiğiyle oylamaya geçsin</td>
      <td>CONSUL DEMOCRACY</td>
    </tr>
    <tr>
      <td>Sorunlar haritada işaretlenip kuruma gönderilsin</td>
      <td>FixMyStreet</td>
    </tr>
  </tbody>
</table>

<p>Seçimde yalnızca özellik listesini değil; kurulum ekibinin Ruby/Rails deneyimini, barındırma bütçesini, moderasyon kapasitesini, çok dillilik ihtiyacını ve kurum içi süreçleri de değerlendirmek gerekir. En parlak arayüz bile arka tarafta dilekçeyi yanıtlayacak bir iş akışı yoksa dijital bir öneri kutusuna dönüşür.</p>

<p>Sonuç olarak Decidim geniş kapsamlı bir demokrasi laboratuvarı, CONSUL DEMOCRACY yapılandırılmış bir öneri ve oylama motoru, FixMyStreet ise konum tabanlı belediye sorunları için uzmanlaşmış bir araçtır. Başarılı seçim, “Hangisi daha güçlü?” sorusundan önce “Vatandaş hangi sürece katılacak?” sorusunu yanıtlamakla başlar.</p>

<p><img src="/img/dijital-katilim-platformlari-83.svg" alt="dijital-katilim-platformlari-83" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="decidim" /><category term="consul-democracy" /><category term="fixmystreet" /><category term="e-demokrasi" /><category term="açık-kaynak" /><category term="dijital-katılım" /><summary type="html"><![CDATA[Bir mahalledeki bozuk kaldırımı bildirmek, belediyeye yeni bir bisiklet yolu önermek veya belirli bir konuda binlerce imza toplamak istiyorsanız sıradan bir formdan fazlasına ihtiyacınız vardır. Decidim, CONSUL DEMOCRACY ve FixMyStreet; vatandaşlarla kurumlar arasında dijital köprü kuran açık kaynaklı platformlardır. Ancak aynı aileden görünseler de farklı problemleri çözerler.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/dijital-katilim-platformlari-83.png" /><media:content medium="image" url="https://program.sonsuz.us/img/dijital-katilim-platformlari-83.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Dijital Oylama Arenası: Helios Voting, Decidim ve CIVS</title><link href="https://program.sonsuz.us/posts/dijital-oylama-arenasi-helios-voting-decidim-ve-civs/" rel="alternate" type="text/html" title="Dijital Oylama Arenası: Helios Voting, Decidim ve CIVS" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/dijital-oylama-arenasi-helios-voting-decidim-ve-civs</id><content type="html" xml:base="https://program.sonsuz.us/posts/dijital-oylama-arenasi-helios-voting-decidim-ve-civs/"><![CDATA[<p>Bir dijital oylama sistemi seçmek, yalnızca “en çok oy alan kazansın” kodu yazmaktan ibaret değildir. Gizlilik, doğrulanabilirlik, kimlik denetimi ve seçim yöntemleri işin içine girdiğinde küçük bir anket hızla kriptografi laboratuvarına dönüşebilir. Bu yazıda Helios Voting, Decidim ve CIVS’nin farklı yaklaşımlarını karşılaştıracağız.</p>

<p>``</p>

<h2 id="oylamanın-teorik-temeli">Oylamanın teorik temeli</h2>

<p>Basit çoğunluk oylamasında aday $i$ için kullanılan oy sayısını $v_i$ ile gösterirsek kazanan şöyle bulunur:</p>

\[kazanan = argmax_i(v_i)\]

<p>Ancak gerçek dünyadaki her karar “tek aday seç” biçiminde değildir. Seçmenler adayları sıralayabilir, birden fazla seçeneği destekleyebilir veya bütçe önerilerine oy verebilir. Ayrıca sistemin dört temel beklentiyi dengelemesi gerekir:</p>

<ul>
  <li><strong>Gizlilik:</strong> Bir oyun kime ait olduğu açıklanmamalıdır.</li>
  <li><strong>Bütünlük:</strong> Oylar değiştirilememeli veya silinememelidir.</li>
  <li><strong>Doğrulanabilirlik:</strong> Seçmen, oyunun sayıma katıldığını kontrol edebilmelidir.</li>
  <li><strong>Uygunluk:</strong> Yalnızca yetkili kişiler ve izin verilen sayıda oy kullanabilmelidir.</li>
</ul>

<p>Bu özellikler bazen çatışır. Kimlik doğrulamasını güçlendirmek gizlilik riskini artırabilir; tamamen anonim katılım ise mükerrer oyları engellemeyi zorlaştırabilir.</p>

<h2 id="üç-platform-üç-farklı-karakter">Üç platform, üç farklı karakter</h2>

<table>
  <thead>
    <tr>
      <th>Platform</th>
      <th>Temel yaklaşım</th>
      <th>Güçlü olduğu alan</th>
      <th>Dikkat edilmesi gereken nokta</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Helios Voting</strong></td>
      <td>Uçtan uca doğrulanabilir kriptografik seçim</td>
      <td>Üniversite, dernek ve kurul seçimleri</td>
      <td>Zorlayıcıya karşı dayanıklılık ve cihaz güvenliği ayrıca değerlendirilmelidir</td>
    </tr>
    <tr>
      <td><strong>Decidim</strong></td>
      <td>Katılımcı demokrasi platformu</td>
      <td>Öneriler, toplantılar, süreçler ve katılımcı bütçeleme</td>
      <td>Tek başına özel amaçlı kriptografik seçim motoru değildir</td>
    </tr>
    <tr>
      <td><strong>CIVS</strong></td>
      <td>Condorcet tabanlı sıralamalı oylama</td>
      <td>Alternatifleri tercih sırasına koyma</td>
      <td>Sonuç yöntemi kullanıcıya önceden açıklanmalıdır</td>
    </tr>
  </tbody>
</table>

<h2 id="helios-voting-matematik-sandık-başında">Helios Voting: Matematik sandık başında</h2>

<p>Helios, oyları açık anahtarlı şifreleme ile korur ve seçim sonucunun doğrulanabilmesi için kriptografik kanıtlar üretir. Homomorfik şifrelemenin sadeleştirilmiş fikri şudur:</p>

\[E(v_1) \otimes E(v_2) = E(v_1 + v_2)\]

<p>Yani sistem, tek tek oyların içeriğini açmadan şifreli oyları birleştirip toplamı elde edebilir. Seçmen genellikle oyuna karşılık gelen bir takip değeri alır ve bu değerin yayımlanan sandık kayıtlarında bulunup bulunmadığını denetler. Böylece “oyum kayboldu mu?” sorusu teknik olarak kontrol edilebilir.</p>

<p>Bununla birlikte uçtan uca doğrulanabilirlik, seçmenin cihazında zararlı yazılım bulunmadığını otomatik olarak garanti etmez. Resmî ve yüksek riskli seçimlerde bağımsız güvenlik incelemesi şarttır.</p>

<h2 id="decidim-oylamadan-daha-büyük-bir-sahne">Decidim: Oylamadan daha büyük bir sahne</h2>

<p>Ruby on Rails tabanlı açık kaynak Decidim, yalnızca sandık kurmaz; karar alma sürecini baştan sona modellemeye çalışır. Katılımcılar öneri oluşturabilir, tartışabilir, toplantılara katılabilir ve bütçe projelerini destekleyebilir.</p>

<p>Bu nedenle Decidim’i “seçim uygulaması” yerine <strong>katılım altyapısı</strong> olarak düşünmek daha doğrudur. Bir belediyenin park önerilerini toplaması, projeleri tartışmaya açması ve ardından bütçe oylaması yapması için uygundur. Süreç şeffaflığı güçlüdür; fakat gizli oy gerektiren kritik seçimlerde kullanılacak özel bileşenler ayrıca incelenmelidir.</p>

<h2 id="civs-tercih-sıralarının-gücü">CIVS: Tercih sıralarının gücü</h2>

<p>CIVS, seçmenlerin adayları sıralamasına dayanır. Condorcet yaklaşımında bir aday, diğer her adayı ikili karşılaştırmada yeniyorsa kazanan kabul edilir. $P(a,b)$, $a$ adayını $b$ adayına tercih edenlerin sayısı olsun:</p>

\[a \succ b \quad eğer \quad P(a,b) &gt; P(b,a)\]

<p>Bu yöntem, yalnızca birinci tercihleri saymak yerine seçmenlerin genel eğilimini yakalar. Ancak döngüler oluşabilir: A, B’yi; B, C’yi; C de A’yı yenebilir. CIVS bu durumları çözmek için belirli Condorcet tamamlayıcı yöntemlerinden yararlanır.</p>

<p>Aşağıdaki Python kodu, iki aday arasındaki basit ikili üstünlüğü hesaplar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">pairwise_winner</span><span class="p">(</span><span class="n">rankings</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="n">scores</span> <span class="o">=</span> <span class="p">{</span><span class="n">a</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="mi">0</span><span class="p">}</span>

    <span class="k">for</span> <span class="n">ranking</span> <span class="ow">in</span> <span class="n">rankings</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">ranking</span><span class="p">.</span><span class="nf">index</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">ranking</span><span class="p">.</span><span class="nf">index</span><span class="p">(</span><span class="n">b</span><span class="p">):</span>
            <span class="n">scores</span><span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">scores</span><span class="p">[</span><span class="n">b</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">if</span> <span class="n">scores</span><span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">==</span> <span class="n">scores</span><span class="p">[</span><span class="n">b</span><span class="p">]:</span>
        <span class="k">return</span> <span class="sh">'</span><span class="s">berabere</span><span class="sh">'</span>
    <span class="k">return</span> <span class="nf">max</span><span class="p">(</span><span class="n">scores</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">scores</span><span class="p">.</span><span class="n">get</span><span class="p">)</span>
</code></pre></div></div>

<p>Fonksiyon, her sıralamada hangi adayın daha yukarıda bulunduğunu kontrol eder. Gerçek bir Condorcet sistemi, bu işlemi bütün aday çiftleri için yaparak bir karşılaştırma matrisi oluşturur.</p>

<h2 id="hangisini-seçmeli">Hangisini seçmeli?</h2>

<p>Kriptografik doğrulanabilirlik önceliğinizse <strong>Helios</strong>, kapsamlı katılımcı süreçler tasarlıyorsanız <strong>Decidim</strong>, seçenekleri adil biçimde sıralamak istiyorsanız <strong>CIVS</strong> güçlü adaylardır. Son karar; tehdit modeline, seçmen kitlesine, kimlik doğrulama ihtiyacına ve kullanılan seçim yönteminin anlaşılabilirliğine dayanmalıdır. Unutmayın: İyi bir dijital sandık yalnızca doğru sonucu üretmez, sonucun neden güvenilir olduğunu da gösterebilir.</p>

<p><img src="/img/dijital-oylama-arenasi-92.svg" alt="dijital-oylama-arenasi-92" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="oylama" /><category term="helios-voting" /><category term="decidim" /><category term="civs" /><category term="e-demokrasi" /><category term="açık-kaynak" /><summary type="html"><![CDATA[Bir dijital oylama sistemi seçmek, yalnızca “en çok oy alan kazansın” kodu yazmaktan ibaret değildir. Gizlilik, doğrulanabilirlik, kimlik denetimi ve seçim yöntemleri işin içine girdiğinde küçük bir anket hızla kriptografi laboratuvarına dönüşebilir. Bu yazıda Helios Voting, Decidim ve CIVS’nin farklı yaklaşımlarını karşılaştıracağız.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/dijital-oylama-arenasi-92.png" /><media:content medium="image" url="https://program.sonsuz.us/img/dijital-oylama-arenasi-92.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Lig ve Puan Tablosu Sistemi Tasarlamak: Fikstürden Şampiyonluğa</title><link href="https://program.sonsuz.us/posts/lig-ve-puan-tablosu-sistemi-tasarlamak-fiksturden-sampiyonluga/" rel="alternate" type="text/html" title="Lig ve Puan Tablosu Sistemi Tasarlamak: Fikstürden Şampiyonluğa" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/lig-ve-puan-tablosu-sistemi-tasarlamak-fiksturden-sampiyonluga</id><content type="html" xml:base="https://program.sonsuz.us/posts/lig-ve-puan-tablosu-sistemi-tasarlamak-fiksturden-sampiyonluga/"><![CDATA[<p>Bir lig yönetim sistemi dışarıdan yalnızca takımları sıralayan basit bir tablo gibi görünür. Oysa Open Tournament veya Tournament Software benzeri bir uygulama; fikstür oluşturma, sonuç kaydetme, eşitlik bozma, hükmen galibiyet ve farklı turnuva formatlarını yönetme gibi birçok kuralı aynı potada eritir. Gelin bu dijital hakemin nasıl tasarlanabileceğine bakalım.</p>

<p><img src="/img/lig-ve-puan-58.svg" alt="lig-ve-puan-58" /></p>

<p>``</p>
<h2 id="temel-veri-modeli">Temel veri modeli</h2>

<p>Sistemin merkezinde <strong>turnuva</strong>, <strong>katılımcı</strong>, <strong>karşılaşma</strong> ve <strong>puan durumu kaydı</strong> bulunur. Katılımcı bir takım olabileceği gibi tekil bir sporcu da olabilir. Bu nedenle veri modelinde <code class="language-plaintext highlighter-rouge">team</code> yerine daha genel olan <code class="language-plaintext highlighter-rouge">participant</code> adını kullanmak sistemi farklı spor dallarına uyarlamayı kolaylaştırır.</p>

<table>
  <thead>
    <tr>
      <th>Varlık</th>
      <th>Önemli alanlar</th>
      <th>Sorumluluk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tournament</td>
      <td>ad, format, kurallar</td>
      <td>Organizasyon ayarlarını saklar</td>
    </tr>
    <tr>
      <td>Participant</td>
      <td>ad, kategori, seri başı</td>
      <td>Takım veya oyuncuyu temsil eder</td>
    </tr>
    <tr>
      <td>Match</td>
      <td>taraflar, skor, durum</td>
      <td>Karşılaşma sonucunu tutar</td>
    </tr>
    <tr>
      <td>Standing</td>
      <td>puan, averaj, sıralama</td>
      <td>Hesaplanan tabloyu temsil eder</td>
    </tr>
  </tbody>
</table>

<p>Puan tablosunu kalıcı olarak saklamak yerine maç sonuçlarından yeniden hesaplamak çoğu zaman daha güvenlidir. Böylece bir skor düzeltildiğinde eski ve yeni değerlerin birbirine karışması önlenir. Performans gerekiyorsa hesaplanan tablo önbelleğe alınabilir.</p>

<h2 id="puan-hesabının-matematiği">Puan hesabının matematiği</h2>

<p>Klasik futbol sisteminde galibiyet 3, beraberlik 1 ve mağlubiyet 0 puandır. Bir katılımcının toplam puanı şu şekilde ifade edilir:</p>

\[P = 3G + 1B + 0M\]

<p>Burada $G$ galibiyet, $B$ beraberlik, $M$ ise mağlubiyet sayısıdır. Genel averaj da</p>

\[A = S_{atılan} - S_{yenilen}\]

<p>formülüyle hesaplanır. Ancak masa tenisi, badminton veya e-spor ligleri set oranı, harita farkı ya da doğrudan ikili averaj kullanabilir. Bu yüzden puan kurallarını kodun içine sabitlemek yerine turnuva ayarlarında tanımlamak iyi bir fikirdir.</p>

<table>
  <thead>
    <tr>
      <th>Kriter</th>
      <th>Avantajı</th>
      <th>Dezavantajı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Genel averaj</td>
      <td>Kolay hesaplanır</td>
      <td>Güçsüz rakiplere karşı farkı ödüllendirir</td>
    </tr>
    <tr>
      <td>İkili averaj</td>
      <td>Doğrudan rekabeti önemser</td>
      <td>Çoklu eşitlikte karmaşıklaşır</td>
    </tr>
    <tr>
      <td>Kazanılan maç</td>
      <td>Sonuç odaklıdır</td>
      <td>Beraberlik ağırlığını azaltır</td>
    </tr>
    <tr>
      <td>Fair-play puanı</td>
      <td>Disiplini teşvik eder</td>
      <td>Ana performansa dolaylı bağlıdır</td>
    </tr>
  </tbody>
</table>

<h2 id="hesaplama-motoru">Hesaplama motoru</h2>

<p>Aşağıdaki TypeScript fonksiyonu, tamamlanmış maçlardan temel puan tablosu üretir. Fonksiyon saf tutulduğu için aynı girdi her zaman aynı çıktıyı verir; test etmek de oldukça kolaydır.</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">type</span> <span class="nx">Match</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">homeId</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">awayId</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">homeScore</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">awayScore</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">status</span><span class="p">:</span> <span class="dl">"</span><span class="s2">finished</span><span class="dl">"</span> <span class="o">|</span> <span class="dl">"</span><span class="s2">scheduled</span><span class="dl">"</span><span class="p">;</span>
<span class="p">};</span>

<span class="kd">type</span> <span class="nx">Row</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">id</span><span class="p">:</span> <span class="kr">string</span><span class="p">;</span>
  <span class="nl">played</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">won</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">draw</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">lost</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">scored</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">conceded</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
  <span class="nl">points</span><span class="p">:</span> <span class="kr">number</span><span class="p">;</span>
<span class="p">};</span>

<span class="kd">function</span> <span class="nf">calculateTable</span><span class="p">(</span><span class="nx">ids</span><span class="p">:</span> <span class="kr">string</span><span class="p">[],</span> <span class="nx">matches</span><span class="p">:</span> <span class="nx">Match</span><span class="p">[]):</span> <span class="nx">Row</span><span class="p">[]</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="nx">rows</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Map</span><span class="p">(</span><span class="nx">ids</span><span class="p">.</span><span class="nf">map</span><span class="p">(</span><span class="nx">id</span> <span class="o">=&gt;</span> <span class="p">[</span><span class="nx">id</span><span class="p">,</span> <span class="p">{</span>
    <span class="nx">id</span><span class="p">,</span> <span class="na">played</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="na">won</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="na">draw</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="na">lost</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
    <span class="na">scored</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="na">conceded</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="na">points</span><span class="p">:</span> <span class="mi">0</span>
  <span class="p">}]));</span>

  <span class="k">for </span><span class="p">(</span><span class="kd">const</span> <span class="nx">match</span> <span class="k">of</span> <span class="nx">matches</span><span class="p">.</span><span class="nf">filter</span><span class="p">(</span><span class="nx">m</span> <span class="o">=&gt;</span> <span class="nx">m</span><span class="p">.</span><span class="nx">status</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">finished</span><span class="dl">"</span><span class="p">))</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">home</span> <span class="o">=</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="nx">match</span><span class="p">.</span><span class="nx">homeId</span><span class="p">)</span><span class="o">!</span><span class="p">;</span>
    <span class="kd">const</span> <span class="nx">away</span> <span class="o">=</span> <span class="nx">rows</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="nx">match</span><span class="p">.</span><span class="nx">awayId</span><span class="p">)</span><span class="o">!</span><span class="p">;</span>

    <span class="nx">home</span><span class="p">.</span><span class="nx">played</span><span class="o">++</span><span class="p">;</span> <span class="nx">away</span><span class="p">.</span><span class="nx">played</span><span class="o">++</span><span class="p">;</span>
    <span class="nx">home</span><span class="p">.</span><span class="nx">scored</span> <span class="o">+=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">homeScore</span><span class="p">;</span>
    <span class="nx">home</span><span class="p">.</span><span class="nx">conceded</span> <span class="o">+=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">awayScore</span><span class="p">;</span>
    <span class="nx">away</span><span class="p">.</span><span class="nx">scored</span> <span class="o">+=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">awayScore</span><span class="p">;</span>
    <span class="nx">away</span><span class="p">.</span><span class="nx">conceded</span> <span class="o">+=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">homeScore</span><span class="p">;</span>

    <span class="k">if </span><span class="p">(</span><span class="nx">match</span><span class="p">.</span><span class="nx">homeScore</span> <span class="o">===</span> <span class="nx">match</span><span class="p">.</span><span class="nx">awayScore</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">home</span><span class="p">.</span><span class="nx">draw</span><span class="o">++</span><span class="p">;</span> <span class="nx">away</span><span class="p">.</span><span class="nx">draw</span><span class="o">++</span><span class="p">;</span>
      <span class="nx">home</span><span class="p">.</span><span class="nx">points</span><span class="o">++</span><span class="p">;</span> <span class="nx">away</span><span class="p">.</span><span class="nx">points</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
      <span class="kd">const</span> <span class="nx">winner</span> <span class="o">=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">homeScore</span> <span class="o">&gt;</span> <span class="nx">match</span><span class="p">.</span><span class="nx">awayScore</span> <span class="p">?</span> <span class="nx">home</span> <span class="p">:</span> <span class="nx">away</span><span class="p">;</span>
      <span class="kd">const</span> <span class="nx">loser</span> <span class="o">=</span> <span class="nx">winner</span> <span class="o">===</span> <span class="nx">home</span> <span class="p">?</span> <span class="nx">away</span> <span class="p">:</span> <span class="nx">home</span><span class="p">;</span>
      <span class="nx">winner</span><span class="p">.</span><span class="nx">won</span><span class="o">++</span><span class="p">;</span> <span class="nx">winner</span><span class="p">.</span><span class="nx">points</span> <span class="o">+=</span> <span class="mi">3</span><span class="p">;</span>
      <span class="nx">loser</span><span class="p">.</span><span class="nx">lost</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="p">[...</span><span class="nx">rows</span><span class="p">.</span><span class="nf">values</span><span class="p">()].</span><span class="nf">sort</span><span class="p">((</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span>
    <span class="nx">b</span><span class="p">.</span><span class="nx">points</span> <span class="o">-</span> <span class="nx">a</span><span class="p">.</span><span class="nx">points</span> <span class="o">||</span>
    <span class="p">(</span><span class="nx">b</span><span class="p">.</span><span class="nx">scored</span> <span class="o">-</span> <span class="nx">b</span><span class="p">.</span><span class="nx">conceded</span><span class="p">)</span> <span class="o">-</span> <span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">scored</span> <span class="o">-</span> <span class="nx">a</span><span class="p">.</span><span class="nx">conceded</span><span class="p">)</span> <span class="o">||</span>
    <span class="nx">b</span><span class="p">.</span><span class="nx">scored</span> <span class="o">-</span> <span class="nx">a</span><span class="p">.</span><span class="nx">scored</span>
  <span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Sıralama zinciri burada puan, averaj ve atılan skor biçimindedir. İkili averaj gerekiyorsa eşit puanlı katılımcılar belirlenmeli, yalnızca kendi aralarındaki maçlardan geçici bir mini tablo oluşturulmalıdır.</p>

<h2 id="fikstür-ve-operasyonel-ayrıntılar">Fikstür ve operasyonel ayrıntılar</h2>

<p>Tek devreli ligde $n$ katılımcı için toplam maç sayısı</p>

\[M = \frac{n(n-1)}{2}\]

<p>olur. Çift devreli ligde bu değer ikiyle çarpılır. Round-robin fikstür için kullanılan <strong>çember yöntemi</strong>, katılımcıları her tur döndürerek herkesin birbiriyle karşılaşmasını sağlar. Katılımcı sayısı tekse hayali bir <code class="language-plaintext highlighter-rouge">BYE</code> eklenir ve onunla eşleşen taraf haftayı maç yapmadan geçirir.</p>

<p>Gerçek dünyada maç erteleme, hükmen sonuç, katılımcı çekilmesi ve yönetici düzeltmeleri unutulmamalıdır. Her skor değişikliğini kullanıcı, zaman ve eski değer bilgisiyle bir denetim günlüğüne kaydetmek tartışmaları azaltır. Sonuç girişini yetkilendirme, eşzamanlı güncellemelerde transaction kullanma ve hesaplama motorunu bolca birim testiyle sınama da sistemin görünmeyen savunma hattıdır. Böylece puan tablosu yalnızca şık değil, son düdüğe kadar güvenilir olur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="typescript" /><category term="nodejs" /><category term="veritabanı" /><category term="algoritma" /><category term="turnuva" /><category term="puan-tablosu" /><summary type="html"><![CDATA[Bir lig yönetim sistemi dışarıdan yalnızca takımları sıralayan basit bir tablo gibi görünür. Oysa Open Tournament veya Tournament Software benzeri bir uygulama; fikstür oluşturma, sonuç kaydetme, eşitlik bozma, hükmen galibiyet ve farklı turnuva formatlarını yönetme gibi birçok kuralı aynı potada eritir. Gelin bu dijital hakemin nasıl tasarlanabileceğine bakalım.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/lig-ve-puan-58.png" /><media:content medium="image" url="https://program.sonsuz.us/img/lig-ve-puan-58.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Üyelik ve Topluluk Sistemi Seçimi: HumHub, BuddyPress ve Discourse</title><link href="https://program.sonsuz.us/posts/uyelik-ve-topluluk-sistemi-secimi-humhub-buddypress-ve-discourse/" rel="alternate" type="text/html" title="Üyelik ve Topluluk Sistemi Seçimi: HumHub, BuddyPress ve Discourse" /><published>2026-10-09T00:00:00+00:00</published><updated>2026-10-09T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/uyelik-ve-topluluk-sistemi-secimi-humhub-buddypress-ve-discourse</id><content type="html" xml:base="https://program.sonsuz.us/posts/uyelik-ve-topluluk-sistemi-secimi-humhub-buddypress-ve-discourse/"><![CDATA[<p><img src="/img/uyelik-ve-topluluk-97.svg" alt="uyelik-ve-topluluk-97" /></p>

<p>Bir topluluk platformu kurmak, yalnızca kullanıcıların kayıt olabileceği bir sayfa hazırlamak değildir. Profil yönetimi, içerik üretimi, bildirimler, moderasyon, yetkilendirme ve kullanıcıların geri dönmesini sağlayan sosyal mekanikler birlikte düşünülmelidir. HumHub, BuddyPress ve Discourse bu problemi farklı açılardan çözer: biri sosyal ağ, biri WordPress eklentisi, diğeri ise modern forum yaklaşımını benimser.</p>

<p>``</p>

<h2 id="önce-topluluk-sisteminin-mantığı">Önce topluluk sisteminin mantığı</h2>

<p>Bir üyelik sisteminin merkezinde <strong>kimlik</strong>, <strong>yetki</strong> ve <strong>etkileşim</strong> bulunur. Kimlik katmanı kullanıcının kim olduğunu; yetkilendirme katmanı hangi işlemleri yapabileceğini; etkileşim katmanı ise diğer üyelerle nasıl iletişim kuracağını belirler.</p>

<p>Basit bir topluluk veri modeli şöyle düşünülebilir:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Kullanıcı → Profil → Rol
Kullanıcı → İçerik → Yorum
Kullanıcı → Grup → Üyelik
İçerik → Bildirim → Kullanıcı
</code></pre></div></div>

<p>Topluluk sağlığını ölçmek için yalnızca kayıtlı kullanıcı sayısına bakmak yanıltıcıdır. Daha anlamlı bir ölçü, aktif kullanıcı oranıdır:</p>

\[A = \frac{Günlük\ aktif\ kullanıcı}{Toplam\ kayıtlı\ kullanıcı} \times 100\]

<p>Örneğin 10.000 üyenin yalnızca 200’ü günlük olarak geri dönüyorsa aktiflik oranı yüzde 2’dir. Dolayısıyla yazılım seçerken özellik listesinden çok, hedeflenen etkileşim biçimine odaklanmak gerekir.</p>

<h2 id="üç-platformun-karakteri">Üç platformun karakteri</h2>

<table>
  <thead>
    <tr>
      <th>Platform</th>
      <th>Temel yaklaşım</th>
      <th>Güçlü olduğu alan</th>
      <th>Teknik yapı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>HumHub</td>
      <td>Özel sosyal ağ</td>
      <td>Gruplar, profiller, kurum içi iletişim</td>
      <td>PHP, Yii, MySQL</td>
    </tr>
    <tr>
      <td>BuddyPress</td>
      <td>WordPress’e sosyal katman</td>
      <td>İçerik sitesiyle üyeliği birleştirme</td>
      <td>PHP, WordPress, MySQL</td>
    </tr>
    <tr>
      <td>Discourse</td>
      <td>Tartışma ve bilgi paylaşımı</td>
      <td>Forumlar, destek toplulukları</td>
      <td>Ruby on Rails, PostgreSQL, Redis</td>
    </tr>
  </tbody>
</table>

<h3 id="humhub">HumHub</h3>

<p>HumHub, Facebook benzeri akışların ve çalışma alanlarının önemli olduğu projelerde öne çıkar. Kullanıcılar profil oluşturabilir, alanlara katılabilir, gönderi paylaşabilir ve birbirlerini takip edebilir. Üniversite kulübü, şirket içi ağ veya kapalı meslek topluluğu için doğal bir seçimdir.</p>

<p>Modüler yapısı sayesinde takvim, görev ve dosya paylaşımı gibi yetenekler eklenebilir. Ancak tema ve modül ekosistemi WordPress kadar geniş değildir. Sunucu yönetimi konusunda temel Linux, PHP ve veritabanı bilgisi gerekir.</p>

<h3 id="buddypress">BuddyPress</h3>

<p>BuddyPress bağımsız bir uygulama değil, WordPress’i topluluk sistemine dönüştüren bir eklentidir. Mevcut sitenizde blog, kurs, mağaza veya üyelik altyapısı varsa oldukça pratiktir. WooCommerce ve LMS eklentileriyle beraber kullanıldığında ücretli topluluklar kurulabilir.</p>

<p>WordPress kancaları üzerinden davranış eklemek mümkündür:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">add_action</span><span class="p">(</span><span class="s1">'bp_init'</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="c1">// BuddyPress yüklendikten sonra özel topluluk işlemlerini başlatır.</span>
    <span class="k">if</span> <span class="p">(</span><span class="nf">is_user_logged_in</span><span class="p">())</span> <span class="p">{</span>
        <span class="nf">update_user_meta</span><span class="p">(</span><span class="nf">get_current_user_id</span><span class="p">(),</span> <span class="s1">'son_topluluk_girisi'</span><span class="p">,</span> <span class="nb">time</span><span class="p">());</span>
    <span class="p">}</span>
<span class="p">});</span>
</code></pre></div></div>

<p>Bu kod, giriş yapmış üyenin son topluluk ziyaretini kaydeder. Böylece geri dönüş oranı veya pasif üyeler analiz edilebilir. Bununla birlikte çok sayıda eklenti kullanmak performans, güvenlik ve uyumluluk sorunları doğurabilir.</p>

<h3 id="discourse">Discourse</h3>

<p>Discourse, klasik forumları daha akıcı hale getirir. Güven seviyeleri, güçlü moderasyon araçları, e-posta ile yanıt, rozetler ve gerçek zamanlı bildirimler hazır gelir. Teknik destek, açık kaynak proje veya soru-cevap odaklı topluluklar için başarılıdır.</p>

<p>Platformun güven sistemi, olumlu davranış sergileyen kullanıcılara zamanla daha fazla yetki verir. Bu yaklaşım moderasyon yükünü topluluğa dağıtır. Docker tabanlı önerilen kurulum güvenilir olsa da düşük kaynaklı paylaşımlı hosting paketlerine pek uygun değildir.</p>

<h2 id="hangisini-seçmelisiniz">Hangisini seçmelisiniz?</h2>

<table>
  <thead>
    <tr>
      <th>İhtiyaç</th>
      <th>Öneri</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kurum içi sosyal ağ</td>
      <td>HumHub</td>
    </tr>
    <tr>
      <td>WordPress tabanlı üyelik sitesi</td>
      <td>BuddyPress</td>
    </tr>
    <tr>
      <td>Destek, tartışma ve bilgi arşivi</td>
      <td>Discourse</td>
    </tr>
    <tr>
      <td>E-ticaretle bütünleşme</td>
      <td>BuddyPress</td>
    </tr>
    <tr>
      <td>Güçlü yerleşik moderasyon</td>
      <td>Discourse</td>
    </tr>
  </tbody>
</table>

<p>Karar verirken toplam maliyeti $M = K + B + E$ biçiminde değerlendirebilirsiniz. Burada $K$ kurulum, $B$ bakım, $E$ ise eklenti ve entegrasyon gideridir. Yazılımların açık kaynak olması, işletmenin tamamen ücretsiz olacağı anlamına gelmez.</p>

<p>Özetle sosyal akış ve gruplar için HumHub, WordPress ekosistemi için BuddyPress, uzun ömürlü tartışmalar için Discourse daha uygundur. En iyi platform, en çok özelliğe sahip olan değil; üyelerin neden geri geleceği sorusuna en net cevabı verendir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="humhub" /><category term="buddypress" /><category term="discourse" /><category term="topluluk" /><category term="üyelik" /><category term="açık-kaynak" /><summary type="html"><![CDATA[Bir topluluk platformu kurmak, yalnızca kullanıcıların kayıt olabileceği bir sayfa hazırlamak değildir. Profil yönetimi, içerik üretimi, bildirimler, moderasyon, yetkilendirme ve kullanıcıların geri dönmesini sağlayan sosyal mekanikler birlikte düşünülmelidir. HumHub, BuddyPress ve Discourse bu problemi farklı açılardan çözer: biri sosyal ağ, biri WordPress eklentisi, diğeri ise modern forum yaklaşımını benimser.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/uyelik-ve-topluluk-97.png" /><media:content medium="image" url="https://program.sonsuz.us/img/uyelik-ve-topluluk-97.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Algoritma Yarışmalarının Perde Arkası: DOMjudge, DMOJ ve CMS</title><link href="https://program.sonsuz.us/posts/algoritma-yarismalarinin-perde-arkasi-domjudge-dmoj-ve-cms/" rel="alternate" type="text/html" title="Algoritma Yarışmalarının Perde Arkası: DOMjudge, DMOJ ve CMS" /><published>2026-10-08T00:00:00+00:00</published><updated>2026-10-08T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/algoritma-yarismalarinin-perde-arkasi-domjudge-dmoj-ve-cms</id><content type="html" xml:base="https://program.sonsuz.us/posts/algoritma-yarismalarinin-perde-arkasi-domjudge-dmoj-ve-cms/"><![CDATA[<p>Bir algoritma yarışmasında çözümünüzü gönderip birkaç saniye sonra “Accepted” sonucunu gördüğünüzde arka planda küçük bir yazılım orkestrası çalışır. Kaynak kod derlenir, izole bir ortamda test edilir, süre ve bellek tüketimi ölçülür, çıktı karşılaştırılır ve puan hesaplanır. DOMjudge, DMOJ ve CMS, bu orkestrayı yöneten en popüler açık kaynak yarışma sistemleri arasındadır.
``</p>

<h2 id="online-judge-nasıl-çalışır">Online judge nasıl çalışır?</h2>

<p>Bir değerlendirme sisteminin temel girdileri kaynak kod, programlama dili ve problem kimliğidir. Sistem önce kodu derler, ardından her test için programı çalıştırır. En basit toplam değerlendirme süresi şöyle düşünülebilir:</p>

\[T_{toplam} = T_{derleme} + \sum_{i=1}^{n} T_{test_i}\]

<p>Programın herhangi bir testte süre sınırını aşması <strong>TLE</strong>, fazla bellek kullanması <strong>MLE</strong>, hatalı çıktı üretmesi ise <strong>WA</strong> sonucuna yol açar. Doğru sonuç yalnızca çıktının doğru olması değildir; programın belirlenen kaynak sınırları içinde çalışması da gerekir.</p>

<p>Gönderilen kod güvenilir kabul edilmez. Sonsuz döngüye girebilir, süreç oluşturmaya çalışabilir veya dosya sistemine erişmek isteyebilir. Bu nedenle judge sunucuları Linux kullanıcıları, cgroups, chroot, container veya benzeri izolasyon mekanizmalarından yararlanır. Kısacası değerlendirme sunucusu, yarışmacının koduna “Seni çalıştırırım ama evin anahtarını vermem” der.</p>

<h2 id="üç-platformun-karşılaştırması">Üç platformun karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>DOMjudge</th>
      <th>DMOJ</th>
      <th>CMS</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ana kullanım</td>
      <td>ICPC tarzı yarışmalar</td>
      <td>Eğitim ve çevrim içi arşiv</td>
      <td>IOI tarzı olimpiyatlar</td>
    </tr>
    <tr>
      <td>Puanlama</td>
      <td>Genellikle problem bazlı</td>
      <td>Esnek, kısmi puan destekli</td>
      <td>Alt görev odaklı</td>
    </tr>
    <tr>
      <td>Teknoloji</td>
      <td>PHP, Symfony, MariaDB</td>
      <td>Python, Django, C++ judge</td>
      <td>Python tabanlı servisler</td>
    </tr>
    <tr>
      <td>Kurulum</td>
      <td>Orta</td>
      <td>Orta-zor</td>
      <td>Zor</td>
    </tr>
    <tr>
      <td>Kullanıcı arayüzü</td>
      <td>Yarışma odaklı</td>
      <td>Topluluk ve arşiv odaklı</td>
      <td>Yönetim odaklı</td>
    </tr>
    <tr>
      <td>Güçlü yanı</td>
      <td>Kararlı takım yarışmaları</td>
      <td>Dil ve problem çeşitliliği</td>
      <td>Gelişmiş olimpiyat değerlendirmesi</td>
    </tr>
  </tbody>
</table>

<h2 id="domjudge-icpc-ruhunun-temsilcisi">DOMjudge: ICPC ruhunun temsilcisi</h2>

<p>DOMjudge, takım yarışmaları ve klasik ICPC kuralları için oldukça uygundur. Yanlış gönderimler ceza süresine eklenir; problem çözüldüğünde süre hesabı kesinleşir. Basitleştirilmiş ceza modeli şöyledir:</p>

\[P = T_{kabul} + 20 \times W\]

<p>Burada $T_{kabul}$ kabul dakikası, $W$ ise kabulden önceki yanlış gönderim sayısıdır. DOMjudge; yarışma yönetimi, canlı sıralama, hakem işlemleri ve ayrı judgehost makineleriyle ölçeklendirme konusunda güçlüdür. Üniversite kulübünde gerçekçi bir ICPC provası düzenlemek istiyorsanız genellikle ilk adaydır.</p>

<h2 id="dmoj-esnek-ve-geliştirici-dostu">DMOJ: Esnek ve geliştirici dostu</h2>

<p>DMOJ, sürekli açık problem arşivleri ve eğitim platformları için öne çıkar. Çok sayıda dili destekler; özel checker, interaktif problem ve kısmi puanlama gibi özellikler sunar. Django tabanlı web uygulaması ile değerlendirme düğümleri birbirinden ayrılabilir.</p>

<p>Bir problemin basit yapılandırması kavramsal olarak şöyle görünebilir:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">archive</span><span class="pi">:</span> <span class="s">data.zip</span>
<span class="na">time</span><span class="pi">:</span> <span class="m">2</span>
<span class="na">memory</span><span class="pi">:</span> <span class="m">256</span>
<span class="na">test_cases</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">points</span><span class="pi">:</span> <span class="m">20</span>
    <span class="na">input</span><span class="pi">:</span> <span class="s">sample.in</span>
    <span class="na">output</span><span class="pi">:</span> <span class="s">sample.out</span>
  <span class="pi">-</span> <span class="na">points</span><span class="pi">:</span> <span class="m">80</span>
    <span class="na">batched</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="na">input</span><span class="pi">:</span> <span class="s">secret.in</span>
        <span class="na">output</span><span class="pi">:</span> <span class="s">secret.out</span>
</code></pre></div></div>

<p>Bu yapı süreyi, bellek sınırını ve testlerin puan ağırlığını tanımlar. Gerçek sözdizimi sürüme ve problem paketine göre değişebilse de temel fikir aynıdır: değerlendirme davranışı kod yerine yapılandırmayla açıklanır.</p>

<h2 id="cms-olimpiyat-seviyesinde-kontrol">CMS: Olimpiyat seviyesinde kontrol</h2>

<p>Contest Management System, özellikle IOI biçimindeki yarışmalara yöneliktir. Alt görevler, geri bildirim düzeyleri, token sistemi ve ayrıntılı puanlama senaryolarında çok başarılıdır. Örneğin çözüm ilk alt görevden 20, ikinci alt görevden 30 puan alabilir; en zor grup başarısız olsa bile toplam puan korunur.</p>

<p>CMS güçlüdür ancak kurulumu ve işletimi diğer seçeneklere göre daha fazla sistem yönetimi bilgisi ister. Servislerin dağıtılması, worker makinelerinin hazırlanması ve yarışma verilerinin doğru modellenmesi dikkat gerektirir.</p>

<h2 id="hangisini-seçmeli">Hangisini seçmeli?</h2>

<p>Tek günlük ICPC benzeri bir etkinlik için <strong>DOMjudge</strong>, okul veya topluluk tabanlı sürekli bir soru platformu için <strong>DMOJ</strong>, ulusal olimpiyat düzeyinde alt görevli yarışmalar için <strong>CMS</strong> daha doğal seçimdir. Platformdan bağımsız olarak yedekleme, HTTPS, kaynak izolasyonu ve yarışma öncesi yük testi ihmal edilmemelidir. Çünkü en zor algoritma sorusu bile çözülebilir; yarışma ortasında çöken judge sunucusu ise herkese aynı anda sistem tasarımı dersi verir.</p>

<p><img src="/img/algoritma-yarismalarinin-perde-38.svg" alt="algoritma-yarismalarinin-perde-38" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="algoritma" /><category term="online-judge" /><category term="domjudge" /><category term="dmoj" /><category term="cms" /><category term="programlama-yarışmaları" /><summary type="html"><![CDATA[Bir algoritma yarışmasında çözümünüzü gönderip birkaç saniye sonra “Accepted” sonucunu gördüğünüzde arka planda küçük bir yazılım orkestrası çalışır. Kaynak kod derlenir, izole bir ortamda test edilir, süre ve bellek tüketimi ölçülür, çıktı karşılaştırılır ve puan hesaplanır. DOMjudge, DMOJ ve CMS, bu orkestrayı yöneten en popüler açık kaynak yarışma sistemleri arasındadır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/algoritma-yarismalarinin-perde-38.png" /><media:content medium="image" url="https://program.sonsuz.us/img/algoritma-yarismalarinin-perde-38.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">API Dokümantasyon Sistemi Kurmak: Swagger UI, Redoc ve Docusaurus</title><link href="https://program.sonsuz.us/posts/api-dokumantasyon-sistemi-kurmak-swagger-ui-redoc-ve-docusaurus/" rel="alternate" type="text/html" title="API Dokümantasyon Sistemi Kurmak: Swagger UI, Redoc ve Docusaurus" /><published>2026-10-08T00:00:00+00:00</published><updated>2026-10-08T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/api-dokumantasyon-sistemi-kurmak-swagger-ui-redoc-ve-docusaurus</id><content type="html" xml:base="https://program.sonsuz.us/posts/api-dokumantasyon-sistemi-kurmak-swagger-ui-redoc-ve-docusaurus/"><![CDATA[<p>Bir API geliştirmek yalnızca çalışan endpoint’ler yazmak değildir; diğer geliştiricilerin bu endpoint’leri keşfedebilmesini, deneyebilmesini ve doğru kullanabilmesini sağlamak da işin parçasıdır. Swagger UI, Redoc ve Docusaurus aynı dokümantasyon evreninde yaşasa da farklı sorunları çözer. Gelin bu araçları yarıştırmak yerine birlikte çalıştırabileceğimiz sürdürülebilir bir sistem tasarlayalım.
``</p>
<h2 id="önce-temel-openapi-nedir">Önce temel: OpenAPI nedir?</h2>

<p>OpenAPI, REST tabanlı bir API’nin insanlar ve makineler tarafından okunabilen sözleşmesidir. Endpoint yolları, HTTP metotları, parametreler, veri modelleri, kimlik doğrulama yöntemleri ve olası yanıtlar YAML veya JSON biçiminde tanımlanır.</p>

<p>Bir API sözleşmesini kabaca şu fonksiyonla düşünebiliriz:</p>

\[S = P + R + M + A + E\]

<p>Burada $P$ yolları, $R$ istekleri, $M$ veri modellerini, $A$ kimlik doğrulamayı ve $E$ hata yanıtlarını temsil eder. Sözleşme ne kadar eksiksizse istemci üretimi, test otomasyonu ve geliştirici deneyimi o kadar başarılı olur.</p>

<p>Swagger UI ve Redoc bu sözleşmeyi görselleştirir. Docusaurus ise rehberler, eğitimler, sürüm notları ve kavramsal açıklamalar için genel bir dokümantasyon sitesi sunar.</p>

<h2 id="araçların-karşılaştırması">Araçların karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Swagger UI</th>
      <th>Redoc</th>
      <th>Docusaurus</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ana amaç</td>
      <td>API’yi etkileşimli denemek</td>
      <td>Okunabilir API referansı</td>
      <td>Tam dokümantasyon portalı</td>
    </tr>
    <tr>
      <td>OpenAPI desteği</td>
      <td>Doğrudan</td>
      <td>Doğrudan</td>
      <td>Eklentiyle</td>
    </tr>
    <tr>
      <td>İstek gönderme</td>
      <td>Güçlü</td>
      <td>Sınırlı veya sürüme bağlı</td>
      <td>Yerleşik değil</td>
    </tr>
    <tr>
      <td>Özelleştirme</td>
      <td>Orta</td>
      <td>Güçlü tema seçenekleri</td>
      <td>React ile çok güçlü</td>
    </tr>
    <tr>
      <td>En uygun kullanım</td>
      <td>Test ve keşif</td>
      <td>Referans dokümanı</td>
      <td>Rehber ve içerik yönetimi</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/api-dokumantasyon-sistemi-62.svg" alt="api-dokumantasyon-sistemi-62" /></p>

<p>Kısacası Swagger UI laboratuvar, Redoc düzenli bir ansiklopedi, Docusaurus ise bütün kampüstür.</p>

<h2 id="küçük-bir-openapi-sözleşmesi">Küçük bir OpenAPI sözleşmesi</h2>

<p>Aşağıdaki dosya, kullanıcı bilgisini kimliğe göre döndüren bir endpoint tanımlar:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">openapi</span><span class="pi">:</span> <span class="s">3.0.3</span>
<span class="na">info</span><span class="pi">:</span>
  <span class="na">title</span><span class="pi">:</span> <span class="s">Kullanıcı API</span>
  <span class="na">version</span><span class="pi">:</span> <span class="s">1.0.0</span>
<span class="na">paths</span><span class="pi">:</span>
  <span class="s">/users/{id}</span><span class="err">:</span>
    <span class="na">get</span><span class="pi">:</span>
      <span class="na">summary</span><span class="pi">:</span> <span class="s">Kimliğe göre kullanıcı getirir</span>
      <span class="na">parameters</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">id</span>
          <span class="na">in</span><span class="pi">:</span> <span class="s">path</span>
          <span class="na">required</span><span class="pi">:</span> <span class="kc">true</span>
          <span class="na">schema</span><span class="pi">:</span>
            <span class="na">type</span><span class="pi">:</span> <span class="s">integer</span>
      <span class="na">responses</span><span class="pi">:</span>
        <span class="s1">'</span><span class="s">200'</span><span class="err">:</span>
          <span class="na">description</span><span class="pi">:</span> <span class="s">Kullanıcı bulundu</span>
          <span class="na">content</span><span class="pi">:</span>
            <span class="na">application/json</span><span class="pi">:</span>
              <span class="na">schema</span><span class="pi">:</span>
                <span class="na">$ref</span><span class="pi">:</span> <span class="s1">'</span><span class="s">#/components/schemas/User'</span>
      <span class="err">  </span><span class="s1">'</span><span class="s">404'</span><span class="err">:</span>
          <span class="na">description</span><span class="pi">:</span> <span class="s">Kullanıcı bulunamadı</span>
<span class="na">components</span><span class="pi">:</span>
  <span class="na">schemas</span><span class="pi">:</span>
    <span class="na">User</span><span class="pi">:</span>
      <span class="na">type</span><span class="pi">:</span> <span class="s">object</span>
      <span class="na">required</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">id</span><span class="pi">,</span> <span class="nv">name</span><span class="pi">]</span>
      <span class="na">properties</span><span class="pi">:</span>
        <span class="na">id</span><span class="pi">:</span>
          <span class="na">type</span><span class="pi">:</span> <span class="s">integer</span>
        <span class="na">name</span><span class="pi">:</span>
          <span class="na">type</span><span class="pi">:</span> <span class="s">string</span>
</code></pre></div></div>

<p>Bu tanım tek bir doğruluk kaynağıdır. Aynı dosya arayüz oluşturmak, sözleşme testi yapmak veya istemci SDK’sı üretmek için kullanılabilir.</p>

<h2 id="swagger-ui-ve-redocu-çalıştırmak">Swagger UI ve Redoc’u çalıştırmak</h2>

<p>En hızlı yöntem Docker kullanmaktır:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Etkileşimli Swagger UI</span>

docker run <span class="nt">--rm</span> <span class="nt">-p</span> 8080:8080 <span class="se">\</span>
  <span class="nt">-e</span> <span class="nv">SWAGGER_JSON</span><span class="o">=</span>/spec/openapi.yaml <span class="se">\</span>
  <span class="nt">-v</span> <span class="s2">"</span><span class="nv">$PWD</span><span class="s2">:/spec"</span> swaggerapi/swagger-ui

<span class="c"># Okuma odaklı Redoc</span>

docker run <span class="nt">--rm</span> <span class="nt">-p</span> 8081:80 <span class="se">\</span>
  <span class="nt">-e</span> <span class="nv">SPEC_URL</span><span class="o">=</span>openapi.yaml redocly/redoc
</code></pre></div></div>

<p>İlk komut API’yi <code class="language-plaintext highlighter-rouge">localhost:8080</code> üzerinde deneyebilmenizi sağlar. İkinci komut aynı sözleşmeyi daha sade ve referans odaklı bir görünümle sunar. Gerçek projede dosyayı Redoc sunucusunun erişebileceği dizine kopyalamak veya bir URL üzerinden yayımlamak gerekir.</p>

<h2 id="docusaurus-ile-merkezi-portal">Docusaurus ile merkezi portal</h2>

<p>Docusaurus projesinde kavramsal rehberleri Markdown ile tutabilir, API referansına menüden bağlantı verebilirsiniz:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// docusaurus.config.js</span>
<span class="k">export</span> <span class="k">default</span> <span class="p">{</span>
  <span class="na">themeConfig</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">navbar</span><span class="p">:</span> <span class="p">{</span>
      <span class="na">items</span><span class="p">:</span> <span class="p">[</span>
        <span class="p">{</span> <span class="na">to</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/docs/intro</span><span class="dl">'</span><span class="p">,</span> <span class="na">label</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Rehberler</span><span class="dl">'</span> <span class="p">},</span>
        <span class="p">{</span> <span class="na">href</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/api/redoc.html</span><span class="dl">'</span><span class="p">,</span> <span class="na">label</span><span class="p">:</span> <span class="dl">'</span><span class="s1">API Referansı</span><span class="dl">'</span> <span class="p">},</span>
        <span class="p">{</span> <span class="na">href</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/swagger/</span><span class="dl">'</span><span class="p">,</span> <span class="na">label</span><span class="p">:</span> <span class="dl">'</span><span class="s1">API’yi Dene</span><span class="dl">'</span> <span class="p">}</span>
      <span class="p">]</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Bu yapı kullanıcıya üç katman sunar: “Neden kullanmalıyım?” sorusunu rehberler, “Hangi alanlar var?” sorusunu Redoc, “Bu istek gerçekten çalışıyor mu?” sorusunu Swagger UI cevaplar.</p>

<h2 id="sürdürülebilir-iş-akışı">Sürdürülebilir iş akışı</h2>

<p>OpenAPI dosyasını uygulama koduyla aynı depoda saklayın. CI sürecinde sözdizimini doğrulayın, kırıcı değişiklikleri karşılaştırın ve başarılı derlemeden sonra üç aracı da yayımlayın. Sürüm numarasını URL’ye eklemek, eski istemcilerin dokümantasyona erişmesini kolaylaştırır.</p>

<p>Ayrıca örneklerde gerçek erişim anahtarları kullanmayın. Swagger UI üzerindeki yetkilendirme alanlarını yalnızca güvenli test ortamlarına bağlayın. Böylece güzel görünen değil; güncel, test edilebilir ve güvenilir bir API dokümantasyon sistemi elde edersiniz.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="api" /><category term="swagger-ui" /><category term="redoc" /><category term="docusaurus" /><category term="openapi" /><category term="dokümantasyon" /><summary type="html"><![CDATA[Bir API geliştirmek yalnızca çalışan endpoint’ler yazmak değildir; diğer geliştiricilerin bu endpoint’leri keşfedebilmesini, deneyebilmesini ve doğru kullanabilmesini sağlamak da işin parçasıdır. Swagger UI, Redoc ve Docusaurus aynı dokümantasyon evreninde yaşasa da farklı sorunları çözer. Gelin bu araçları yarıştırmak yerine birlikte çalıştırabileceğimiz sürdürülebilir bir sistem tasarlayalım.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/api-dokumantasyon-sistemi-62.png" /><media:content medium="image" url="https://program.sonsuz.us/img/api-dokumantasyon-sistemi-62.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">API Test Arenası: Hoppscotch, Bruno ve Insomnia Karşılaştırması</title><link href="https://program.sonsuz.us/posts/api-test-arenasi-hoppscotch-bruno-ve-insomnia-karsilastirmasi/" rel="alternate" type="text/html" title="API Test Arenası: Hoppscotch, Bruno ve Insomnia Karşılaştırması" /><published>2026-10-08T00:00:00+00:00</published><updated>2026-10-08T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/api-test-arenasi-hoppscotch-bruno-ve-insomnia-karsilastirmasi</id><content type="html" xml:base="https://program.sonsuz.us/posts/api-test-arenasi-hoppscotch-bruno-ve-insomnia-karsilastirmasi/"><![CDATA[<p>Bir API geliştirirken yalnızca endpoint’in çalışması yetmez; doğru durum kodunu, beklenen veriyi ve kabul edilebilir sürede yanıt verdiğini de doğrulamak gerekir. Postman dışında bir araç arıyorsanız Hoppscotch, Bruno ve Insomnia oldukça güçlü üç adaydır. Üstelik her biri API testine farklı bir pencereden bakar: biri hızlı ve web tabanlı, biri Git dostu, diğeri ise kapsamlı bir masaüstü çalışma alanıdır.</p>

<p><img src="/img/api-test-arenasi-95.svg" alt="api-test-arenasi-95" /></p>

<p>``</p>

<h2 id="api-testi-aslında-neyi-doğrular">API testi aslında neyi doğrular?</h2>

<p>Bir istemci API’ye HTTP isteği gönderir; sunucu ise durum kodu, başlıklar ve gövde içeren bir yanıt üretir. Test aracının temel görevi bu alışverişi görünür ve tekrar edilebilir hâle getirmektir.</p>

<p>Örneğin bir kullanıcı endpoint’i için yalnızca <code class="language-plaintext highlighter-rouge">200 OK</code> almak yeterli değildir. Yanıt gövdesindeki <code class="language-plaintext highlighter-rouge">id</code> alanının bulunması, içerik türünün JSON olması ve sürenin belirlenen sınırı aşmaması da kontrol edilmelidir.</p>

<p>Performansı basitçe şöyle değerlendirebiliriz:</p>

\[T_{toplam} = T_{ağ} + T_{sunucu} + T_{aktarım}\]

<p>Bir test 400 ms sürüyorsa bunun tamamı sunucunun işlem süresi değildir. Ağ gecikmesi ve yanıt boyutu da sonucu etkiler. Çoklu isteklerde ortalama süre ise</p>

\[\bar{T} = \frac{\sum_{i=1}^{n} T_i}{n}\]

<p>formülüyle hesaplanabilir. Bu nedenle tek bir hızlı yanıt görüp zafer dansına başlamak yerine testi birkaç kez çalıştırmak daha sağlıklıdır.</p>

<h2 id="üç-aracın-karakteri">Üç aracın karakteri</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Hoppscotch</th>
      <th>Bruno</th>
      <th>Insomnia</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Çalışma biçimi</td>
      <td>Web ve masaüstü</td>
      <td>Masaüstü ve CLI</td>
      <td>Masaüstü</td>
    </tr>
    <tr>
      <td>Başlangıç hızı</td>
      <td>Çok yüksek</td>
      <td>Yüksek</td>
      <td>Orta</td>
    </tr>
    <tr>
      <td>Git uyumu</td>
      <td>Sınırlı</td>
      <td>Çok güçlü</td>
      <td>Projeye göre değişir</td>
    </tr>
    <tr>
      <td>Yerel dosya yaklaşımı</td>
      <td>İkincil</td>
      <td>Temel özellik</td>
      <td>Kısmen</td>
    </tr>
    <tr>
      <td>Otomasyon</td>
      <td>Temel/orta</td>
      <td>CLI ile güçlü</td>
      <td>Eklenti ve CLI seçenekleri</td>
    </tr>
    <tr>
      <td>İdeal kullanıcı</td>
      <td>Hızlı deneme yapanlar</td>
      <td>Kod odaklı ekipler</td>
      <td>Geniş çalışma alanı isteyenler</td>
    </tr>
  </tbody>
</table>

<h3 id="hoppscotch-tarayıcıyı-aç-ve-isteği-gönder">Hoppscotch: Tarayıcıyı aç ve isteği gönder</h3>

<p>Hoppscotch, kurulumla uğraşmadan REST, GraphQL ve WebSocket istekleri denemek isteyenler için idealdir. Arayüzü hafiftir; URL’yi, metodu ve gerekli başlıkları girerek saniyeler içinde sonuç alabilirsiniz. Özellikle eğitimlerde, hata ayıklamada ve geçici kontrollerde parıldar.</p>

<p>Ancak hassas token’larla çalışırken ekip politikalarını ve verinin nerede saklandığını incelemek gerekir. Tarayıcı kolaylığı, güvenlik değerlendirmesini ortadan kaldırmaz.</p>

<h3 id="bruno-koleksiyonlar-da-kod-gibi-yaşasın">Bruno: Koleksiyonlar da kod gibi yaşasın</h3>

<p>Bruno, koleksiyonları düz metin dosyalarında saklayarak Git üzerinden sürümlemeyi kolaylaştırır. Böylece API değişiklikleri pull request içinde görülebilir; “Bu header’ı kim değiştirdi?” sorusu polisiye romana dönüşmez.</p>

<p>Örnek bir Bruno isteği şöyle görünebilir:</p>

<pre><code class="language-bru">meta {
  name: Kullanıcı Getir
  type: http
  seq: 1
}

get {
  url: {{baseUrl}}/users/42
  body: none
  auth: bearer
}

assert {
  res.status: eq 200
  res.body.id: eq 42
}
</code></pre>

<p>Bu dosya isteğin adresini tanımlar ve yanıtın durum koduyla kullanıcı kimliğini doğrular. CLI desteği sayesinde aynı koleksiyon CI/CD hattında da çalıştırılabilir.</p>

<h3 id="insomnia-düzenli-ve-kapsamlı-çalışma-masası">Insomnia: Düzenli ve kapsamlı çalışma masası</h3>

<p>Insomnia; ortam değişkenleri, kimlik doğrulama yöntemleri, GraphQL desteği ve koleksiyon organizasyonuyla kapsamlı projelerde rahat bir deneyim sunar. Çok sayıda servisi olan ekipler için klasörlü yapı ve yeniden kullanılabilir değişkenler önemlidir.</p>

<p>Örneğin geliştirme ve üretim adreslerini ayrı ayrı yazmak yerine şu mantık kullanılabilir:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"base_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://api.example.com"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"token"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{{ secret_token }}"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>Böylece isteklerde `` kullanılır ve ortam değiştirirken her endpoint’i elle düzenlemek gerekmez. Token değerlerini repoya eklememek ise temel güvenlik kuralıdır.</p>

<h2 id="hangisini-seçmelisiniz">Hangisini seçmelisiniz?</h2>

<p>Hızlı, kurulumsuz denemeler için <strong>Hoppscotch</strong>; koleksiyonları Git ile yönetmek ve testleri pipeline’a taşımak için <strong>Bruno</strong>; kapsamlı masaüstü deneyimi ve düzenli proje yönetimi için <strong>Insomnia</strong> öne çıkar. En iyi araç, en fazla düğmeye sahip olan değil, ekibinizin testleri düzenli çalıştırmasını sağlayandır. Küçük bir örnek API’yi üçünde de deneyin; ardından hız, paylaşım, güvenlik ve otomasyon ihtiyaçlarınıza göre karar verin.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="api" /><category term="hoppscotch" /><category term="bruno" /><category term="insomnia" /><category term="rest" /><category term="yazılım-testi" /><summary type="html"><![CDATA[Bir API geliştirirken yalnızca endpoint’in çalışması yetmez; doğru durum kodunu, beklenen veriyi ve kabul edilebilir sürede yanıt verdiğini de doğrulamak gerekir. Postman dışında bir araç arıyorsanız Hoppscotch, Bruno ve Insomnia oldukça güçlü üç adaydır. Üstelik her biri API testine farklı bir pencereden bakar: biri hızlı ve web tabanlı, biri Git dostu, diğeri ise kapsamlı bir masaüstü çalışma alanıdır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/api-test-arenasi-95.png" /><media:content medium="image" url="https://program.sonsuz.us/img/api-test-arenasi-95.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Dijital Hafızanı Kur: Linkwarden, Linkding ve Shaarli Karşılaştırması</title><link href="https://program.sonsuz.us/posts/dijital-hafizani-kur-linkwarden-linkding-ve-shaarli-karsilastirmasi/" rel="alternate" type="text/html" title="Dijital Hafızanı Kur: Linkwarden, Linkding ve Shaarli Karşılaştırması" /><published>2026-10-08T00:00:00+00:00</published><updated>2026-10-08T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/dijital-hafizani-kur-linkwarden-linkding-ve-shaarli-karsilastirmasi</id><content type="html" xml:base="https://program.sonsuz.us/posts/dijital-hafizani-kur-linkwarden-linkding-ve-shaarli-karsilastirmasi/"><![CDATA[<p>Tarayıcı yer imleri bir süre sonra çekmecedeki kablolara benzer: Hepsinin önemli olduğuna eminsindir ama hangisinin ne işe yaradığını bulamazsın. Linkwarden, Linkding ve Shaarli; bağlantıları etiketleyerek saklamayı, aramayı ve kendi sunucunda yönetmeyi sağlayan açık kaynaklı yer imi araçlarıdır. Böylece tarayıcıya veya ticari bir servise bağımlı kalmadan kişisel bir dijital kütüphane kurabilirsin.
``</p>
<h2 id="yer-imi-sistemi-aslında-ne-yapar">Yer imi sistemi aslında ne yapar?</h2>

<p>İyi bir bookmark sistemi yalnızca URL depolamaz. Bir bağlantıyı; başlık, açıklama, etiket, eklenme tarihi ve arşivlenmiş içerikle birlikte saklar. Teorik olarak her kaydı şu kümeyle gösterebiliriz:</p>

\[B = \{u, t, d, E, z, a\}\]

<p>Burada $u$ adresi, $t$ başlığı, $d$ açıklamayı, $E$ etiketler kümesini, $z$ eklenme zamanını ve $a$ arşiv kopyasını temsil eder. Etiketleme sayesinde arama alanı küçülür. Toplam $N$ bağlantının yalnızca belirli bir etikete ait $k$ tanesini incelemek, zihinsel yükü kabaca $N$ öğeden $k$ öğeye indirir.</p>

<p>Örneğin <code class="language-plaintext highlighter-rouge">python</code>, <code class="language-plaintext highlighter-rouge">veritabanı</code> ve <code class="language-plaintext highlighter-rouge">okunacak</code> etiketlerinin kesişimi şöyle düşünülebilir:</p>

\[S = E_{python} \cap E_{veritabanı} \cap E_{okunacak}\]

<p>Bu yaklaşım klasörlerden daha esnektir; çünkü aynı bağlantı birden fazla bağlama ait olabilir.</p>

<h2 id="üç-aracın-karakteri">Üç aracın karakteri</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Linkwarden</th>
      <th>Linkding</th>
      <th>Shaarli</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Arayüz</td>
      <td>Modern ve görsel</td>
      <td>Sade ve hızlı</td>
      <td>Minimal, klasik</td>
    </tr>
    <tr>
      <td>Sayfa arşivleme</td>
      <td>Güçlü; ekran görüntüsü ve belge</td>
      <td>Temel kullanım odaklı</td>
      <td>Sınırlı</td>
    </tr>
    <tr>
      <td>Çoklu kullanıcı</td>
      <td>Uygun</td>
      <td>Daha çok kişisel kullanım</td>
      <td>Temelde kişisel</td>
    </tr>
    <tr>
      <td>Kaynak tüketimi</td>
      <td>Görece yüksek</td>
      <td>Düşük</td>
      <td>Çok düşük</td>
    </tr>
    <tr>
      <td>Teknoloji</td>
      <td>Next.js, PostgreSQL</td>
      <td>Python, SQLite</td>
      <td>PHP, dosya tabanlı</td>
    </tr>
    <tr>
      <td>En iyi senaryo</td>
      <td>Ekip ve kalıcı arşiv</td>
      <td>Hızlı kişisel koleksiyon</td>
      <td>Küçük sunucu</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/dijital-hafizani-kur-71.svg" alt="dijital-hafizani-kur-71" /></p>

<h3 id="linkwarden">Linkwarden</h3>

<p>Linkwarden, bağlantı çürümesine karşı en güçlü seçenektir. Bir web sayfası silinse bile ekran görüntüsü veya PDF benzeri arşivleri koruyabilir. Koleksiyon paylaşımı ve kullanıcı yönetimi sayesinde ekipler için de uygundur. Bunun bedeli daha fazla RAM, depolama ve kurulum bileşenidir.</p>

<h3 id="linkding">Linkding</h3>

<p>Linkding, “yer imimi ekleyeyim ve hemen bulayım” yaklaşımını benimser. Arayüzü dikkat dağıtmaz; etiketleme, arama, içe aktarma ve tarayıcı eklentileri günlük kullanımda oldukça yeterlidir. SQLite kullanması yedeklemeyi de kolaylaştırır: Çoğu durumda veritabanı dosyasını güvenli biçimde kopyalamak yeterlidir.</p>

<h3 id="shaarli">Shaarli</h3>

<p>Shaarli, eski bir dizüstünü sunucuya dönüştürenlerin kahramanıdır. PHP çalıştırabilen mütevazı bir sunucuda yaşayabilir ve veritabanı sunucusu gerektirmez. Arayüzü rakipleri kadar modern değildir; fakat taşınabilirlik ve sadelik konusunda oldukça güçlüdür.</p>

<h2 id="docker-ile-linkding-kurulumu">Docker ile Linkding kurulumu</h2>

<p>Aşağıdaki <code class="language-plaintext highlighter-rouge">compose.yaml</code>, Linkding servisini başlatır ve verileri kalıcı bir klasörde tutar:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">services</span><span class="pi">:</span>
  <span class="na">linkding</span><span class="pi">:</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">sissbruecker/linkding:latest</span>
    <span class="na">container_name</span><span class="pi">:</span> <span class="s">linkding</span>
    <span class="na">ports</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s2">"</span><span class="s">9090:9090"</span>
    <span class="na">volumes</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">./data:/etc/linkding/data</span>
    <span class="na">environment</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">LD_SUPERUSER_NAME=admin</span>
      <span class="pi">-</span> <span class="s">LD_SUPERUSER_PASSWORD=guclu-bir-parola</span>
    <span class="na">restart</span><span class="pi">:</span> <span class="s">unless-stopped</span>
</code></pre></div></div>

<p>Dosyanın bulunduğu dizinde şu komutu çalıştır:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker compose up <span class="nt">-d</span>
</code></pre></div></div>

<p>Ardından <code class="language-plaintext highlighter-rouge">http://sunucu-adresi:9090</code> üzerinden giriş yapabilirsin. <code class="language-plaintext highlighter-rouge">volumes</code> bölümü, konteyner silinse bile kayıtların <code class="language-plaintext highlighter-rouge">data</code> klasöründe kalmasını sağlar. Gerçek kullanımda güçlü parola, HTTPS ve düzenli yedekleme şarttır; yönetim panelini doğrudan internete açmak iyi bir macera türü değildir.</p>

<h2 id="hangisini-seçmelisin">Hangisini seçmelisin?</h2>

<p>Kalıcı web arşivi ve ekip paylaşımı istiyorsan <strong>Linkwarden</strong>, hızlı ve dengeli bir kişisel sistem arıyorsan <strong>Linkding</strong>, en düşük kaynak tüketimiyle bağımsızlık hedefliyorsan <strong>Shaarli</strong> seç. En iyi araç, yüzlerce özelliği olan değil, yeni bağlantı eklemeyi erteletmeyecek kadar rahat olandır. Sistemi seçtikten sonra az sayıda tutarlı etiket belirle, tarayıcıdaki eski yer imlerini içe aktar ve otomatik yedekleme kur. Dijital çekmecen sonunda gerçekten düzenli kalabilir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="yer imi" /><category term="linkwarden" /><category term="linkding" /><category term="shaarli" /><category term="self-hosted" /><category term="docker" /><summary type="html"><![CDATA[Tarayıcı yer imleri bir süre sonra çekmecedeki kablolara benzer: Hepsinin önemli olduğuna eminsindir ama hangisinin ne işe yaradığını bulamazsın. Linkwarden, Linkding ve Shaarli; bağlantıları etiketleyerek saklamayı, aramayı ve kendi sunucunda yönetmeyi sağlayan açık kaynaklı yer imi araçlarıdır. Böylece tarayıcıya veya ticari bir servise bağımlı kalmadan kişisel bir dijital kütüphane kurabilirsin.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/dijital-hafizani-kur-71.png" /><media:content medium="image" url="https://program.sonsuz.us/img/dijital-hafizani-kur-71.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Dosyalar Güvende: Duplicati, BorgBackup ve Restic Karşılaştırması</title><link href="https://program.sonsuz.us/posts/dosyalar-guvende-duplicati-borgbackup-ve-restic-karsilastirmasi/" rel="alternate" type="text/html" title="Dosyalar Güvende: Duplicati, BorgBackup ve Restic Karşılaştırması" /><published>2026-10-08T00:00:00+00:00</published><updated>2026-10-08T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/dosyalar-guvende-duplicati-borgbackup-ve-restic-karsilastirmasi</id><content type="html" xml:base="https://program.sonsuz.us/posts/dosyalar-guvende-duplicati-borgbackup-ve-restic-karsilastirmasi/"><![CDATA[<p>Bir diskin bozulması, yanlışlıkla çalıştırılan bir silme komutu veya fidye yazılımı, yılların verisini saniyeler içinde erişilemez hâle getirebilir. Neyse ki Duplicati, BorgBackup ve Restic; şifreleme, sıkıştırma ve artımlı yedekleme gibi modern özelliklerle “Keşke yedek alsaydım!” cümlesini tarihe gömmeyi amaçlıyor.
``</p>

<h2 id="sağlam-bir-yedekleme-sisteminin-mantığı">Sağlam bir yedekleme sisteminin mantığı</h2>

<p>Yedekleme, dosyaları başka bir klasöre kopyalamaktan ibaret değildir. Güvenilir bir plan için yaygın <strong>3-2-1 kuralı</strong> uygulanabilir:</p>

<ul>
  <li>Verinin en az <strong>3 kopyası</strong> bulunmalı.</li>
  <li>Kopyalar <strong>2 farklı ortamda</strong> tutulmalı.</li>
  <li>Kopyalardan <strong>1 tanesi uzak konumda</strong> olmalı.</li>
</ul>

<p>Depolama ihtiyacını azaltmak için üç araç da artımlı yedekleme yaklaşımından yararlanır. İlk çalıştırmada tüm veri saklanırken sonraki çalıştırmalarda yalnızca değişiklikler gönderilir. Basitleştirilmiş depolama hesabı şöyledir:</p>

\[S = F + \sum_{i=1}^{n} \Delta_i\]

<p>Burada $F$ ilk tam yedeğin boyutunu, $\Delta_i$ ise her çalıştırmada değişen veri miktarını temsil eder. Tekilleştirme sayesinde aynı veri bloklarının tekrar saklanması önlenebilir. Örneğin 10 GB’lık bir dosyanın yalnızca küçük bir bölümü değiştiğinde yeniden 10 GB göndermek gerekmez.</p>

<h2 id="üç-aracın-karşılaştırması">Üç aracın karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Duplicati</th>
      <th>BorgBackup</th>
      <th>Restic</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kullanım biçimi</td>
      <td>Web arayüzü ve CLI</td>
      <td>Komut satırı</td>
      <td>Komut satırı</td>
    </tr>
    <tr>
      <td>İşletim sistemi</td>
      <td>Windows, Linux, macOS</td>
      <td>Özellikle Linux/macOS</td>
      <td>Windows, Linux, macOS</td>
    </tr>
    <tr>
      <td>Tekilleştirme</td>
      <td>Var</td>
      <td>Çok güçlü</td>
      <td>Var</td>
    </tr>
    <tr>
      <td>Şifreleme</td>
      <td>AES-256</td>
      <td>Yerleşik</td>
      <td>Yerleşik</td>
    </tr>
    <tr>
      <td>Uzak depolama</td>
      <td>Çok sayıda bulut servisi</td>
      <td>Genellikle SSH</td>
      <td>S3, SFTP ve çeşitli servisler</td>
    </tr>
    <tr>
      <td>İdeal kullanıcı</td>
      <td>Görsel arayüz isteyenler</td>
      <td>Performans odaklı Linux kullanıcıları</td>
      <td>Taşınabilirlik isteyenler</td>
    </tr>
  </tbody>
</table>

<p><strong>Duplicati</strong>, tarayıcıdan yönetilen arayüzü sayesinde zamanlama, hedef seçimi ve geri yükleme işlemlerini kolaylaştırır. Google Drive, OneDrive ve S3 gibi hedeflere doğrudan bağlanabilmesi önemli bir avantajdır. Buna karşılık büyük yedek kümelerinde veritabanı bakımı gerekebilir.</p>

<p><strong>BorgBackup</strong>, içerik tanımlı parçalama ve güçlü tekilleştirme özellikleriyle özellikle Linux sunucularında parlar. Depoların SSH üzerinden kullanılabilmesi güvenli ve hızlı bir yapı sunar. Ancak grafik arayüz bekleyen kullanıcılar için biraz fazla terminal kokabilir.</p>

<p><strong>Restic</strong> ise sade komutları, tek dosyalık kurulumu ve platformlar arası desteğiyle öne çıkar. Şifreleme varsayılan tasarımın parçasıdır; yedek deposu ele geçirilse bile parola olmadan içerik okunamaz.</p>

<h2 id="borgbackup-ile-örnek-yedekleme">BorgBackup ile örnek yedekleme</h2>

<p>Önce şifreli bir depo oluşturulur, ardından proje dizini arşivlenir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>borg init <span class="nt">--encryption</span><span class="o">=</span>repokey-blake2 /mnt/backup/borg-repo
borg create <span class="nt">--stats</span> /mnt/backup/borg-repo::proje-<span class="o">{</span>now<span class="o">}</span> ~/projeler
</code></pre></div></div>

<p>İlk komut şifreli depoyu hazırlar. İkinci komut, tarih bilgisini taşıyan yeni bir anlık görüntü oluşturur. Eski yedekleri kontrollü biçimde temizlemek için şu politika uygulanabilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>borg prune <span class="nt">--list</span> /mnt/backup/borg-repo <span class="se">\</span>
  <span class="nt">--keep-daily</span><span class="o">=</span>7 <span class="nt">--keep-weekly</span><span class="o">=</span>4 <span class="nt">--keep-monthly</span><span class="o">=</span>6
</code></pre></div></div>

<p>Bu komut son yedi günlük, dört haftalık ve altı aylık yedeği korur.</p>

<h2 id="restic-ile-uzak-hedef-kullanımı">Restic ile uzak hedef kullanımı</h2>

<p>Restic deposu SFTP üzerinde hazırlanabilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">RESTIC_REPOSITORY</span><span class="o">=</span>sftp:user@sunucu:/yedekler/restic
restic init
restic backup ~/Belgeler ~/Fotoğraflar
restic check
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">backup</code> verileri şifreleyerek gönderirken <code class="language-plaintext highlighter-rouge">check</code>, depo bütünlüğünü denetler. Parola otomasyon sırasında açıkça yazılmamalı; izinleri sınırlandırılmış bir parola dosyası veya güvenli sır yönetim sistemi kullanılmalıdır.</p>

<h2 id="hangisini-seçmeli">Hangisini seçmeli?</h2>

<p>Masaüstünde kolay yönetim ve bulut bağlantıları için <strong>Duplicati</strong>, Linux sunucusunda yüksek verimlilik için <strong>BorgBackup</strong>, farklı sistemlerde sade ve güvenli kullanım için <strong>Restic</strong> güçlü adaydır. Hangi araç seçilirse seçilsin, yalnızca yedek almak yeterli değildir. Düzenli geri yükleme testi yapılmayan bir yedek, açılana kadar Schrödinger’in yedeğidir: Hem vardır hem yoktur!</p>

<p><img src="/img/dosyalar-guvende-duplicati-70.svg" alt="dosyalar-guvende-duplicati-70" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="yedekleme" /><category term="duplicati" /><category term="borgbackup" /><category term="restic" /><category term="veri güvenliği" /><category term="linux" /><summary type="html"><![CDATA[Bir diskin bozulması, yanlışlıkla çalıştırılan bir silme komutu veya fidye yazılımı, yılların verisini saniyeler içinde erişilemez hâle getirebilir. Neyse ki Duplicati, BorgBackup ve Restic; şifreleme, sıkıştırma ve artımlı yedekleme gibi modern özelliklerle “Keşke yedek alsaydım!” cümlesini tarihe gömmeyi amaçlıyor.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/dosyalar-guvende-duplicati-70.png" /><media:content medium="image" url="https://program.sonsuz.us/img/dosyalar-guvende-duplicati-70.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>