<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Alihan SARAÇ on Medium]]></title>
        <description><![CDATA[Stories by Alihan SARAÇ on Medium]]></description>
        <link>https://medium.com/@saracalihan?source=rss-9e0746732eba------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*AEp3To-Ey6XRmJO5RZP4XQ.jpeg</url>
            <title>Stories by Alihan SARAÇ on Medium</title>
            <link>https://medium.com/@saracalihan?source=rss-9e0746732eba------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 17 May 2026 10:05:30 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@saracalihan/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[TypeScript’in Sihirli Özelliği: Decorator]]></title>
            <link>https://medium.com/@saracalihan/typescriptin-sihirli-%C3%B6zelli%C4%9Fi-decorator-5431d4a17a3b?source=rss-9e0746732eba------2</link>
            <guid isPermaLink="false">https://medium.com/p/5431d4a17a3b</guid>
            <category><![CDATA[oop]]></category>
            <category><![CDATA[decorators]]></category>
            <category><![CDATA[typescript]]></category>
            <dc:creator><![CDATA[Alihan SARAÇ]]></dc:creator>
            <pubDate>Fri, 05 Apr 2024 08:58:49 GMT</pubDate>
            <atom:updated>2024-04-05T09:00:31.338Z</atom:updated>
            <content:encoded><![CDATA[<p>Daha önce Java, C# gibi dillerle uğraştıysanız sınıf, fonksiyon veya parametrelerin önüne yazılan ve kodun çalışmasını etkileyebilen, köşeli parantez benzeri şeyler kullanılan garip yazımlı kelimelerle karşılaşmışsınızdır. Peki bunların ne olduğunu veya TypeScript ile yapılarınızı nasıl sarmalayacağınızı yahut onlara bazı anlamlar yükleyebileceğinizi hiç merak ettiniz mi? Gelin bunlara birlikte bakalım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Iaj8sy9O4MExQSAdmPzGwg.png" /></figure><h3>Decorator Nedir?</h3><p>Decorator, <strong>sınıf</strong>larla ve içindeki <strong>methot</strong>larla, <strong>parametre</strong>lerle, <strong>property</strong>’lerle, <strong>erişimci</strong>lerle etkileşime girebilen bir tür özel fonksiyonlardır. Bu bahsettiğimiz şeyleri değiştirmemize, içine yeni değerler eklememize, değerlerine göre farklı aksiyonlar almamıza ve de bunlara meta data olarak adlandırdığımız bilgi yükleme olanaklarını bize sağlar.</p><blockquote><strong>JavaScript</strong>’te Dekoratörler henüz <a href="https://nitayneeman.com/posts/introducing-all-stages-of-the-tc39-process-in-ecmascript/#:~:text=Stage%201%20is%20a%20formal,draft%20of%20the%20proposal%20specification"><strong>stage 2</strong></a><strong> seviyesinde</strong> olup <strong>TypeScript</strong>’te ise <strong>deneysel</strong> olarak kullanılmaktadır. <strong>TS 5.0</strong> ile <strong>stage 3 </strong>seviyesine ilerlemiş ve <strong>kullanımında değişiklikler yapılmıştır</strong>. Bu yazı <strong>stage 2</strong> özelliklerini anlatmaktadır.</blockquote><p>Decorator’lar ile annotations ve meta-programming yapılması mümkün hale gelmiştir. Meta data’nın ne olduğunu ve bununla neler yapılabileceğini “<a href="https://medium.com/@saracalihan/c-attributelara-derinlemesine-bak%C4%B1%C5%9F-e34384aec49a">C# Attribute’lara Derinlemesine Bakış</a>” adlı yazımdan detaylıca öğrenebilirsiniz.</p><p>Bunlar dışında nesne üzerindeki verileri doğrulayabilir, fonksiyonunuz çağrıldığında ondan önce çalışacak bir sarmayalıcı oluşturabilirsiniz.</p><h3>Nasıl kullanılır?</h3><p>Decorator’ler hala dile tam olarak eklenmediği için TypeScript Compailer’a decorator kullanacağımızı belirtmemiz gerekiyor. Derleme komutunuza --target ES5 --experimentalDecorators ekleyerek ya da tsconfig.json dosyanıza aşağıdaki key’i ekleyerek kullanıma hazır hale gelebilirsiniz.</p><pre>&quot;<a href="https://www.typescriptlang.org/tsconfig#compilerOptions">compilerOptions</a>&quot;: {<br>  &quot;<a href="https://www.typescriptlang.org/tsconfig#target">target</a>&quot;: &quot;ES5&quot;,<br>  &quot;<a href="https://www.typescriptlang.org/tsconfig#experimentalDecorators">experimentalDecorators</a>&quot;: true<br>}</pre><p>Dekorator’ler @decoratorİsmi şeklinde çağrılır. Run time anında decoratorİsmi fonksiyonuna ifade ettiği alanın bilgileri verilerek çağrılır. İlgili alanların önüne ya da bir üst satırına yazılarak kullanılabilirler ve içlerine parametre alabilirler.</p><pre>@veritabanıTabloİsmi(&#39;users&#39;)<br>class Kullanıcı {<br>  @benzersizOlmalı<br>  email: string;<br>  <br>  @yöneticiMi<br>  set birimNumarası() {}  <br>  @methodDekoratörü<br>  fly( @büyükOlmalıdır(10) meters: number ) {}  <br>}</pre><h4><strong>Çoklu Decorator kullanımı</strong></h4><p>Aynı alan için bieden fazla dekorator kullanımı mümkündür.</p><p>Aralarına boşluk bırakarak tek satırda yazılabilir.</p><pre>@a @b @c<br>function kaydet(){}</pre><p>veya alt alta kullanabilirsiniz.</p><pre>@a<br>@b<br>@c<br>function kaydet(){<br>  console.log(&#39;kaydet fonksiyonu çalişti&#39;);<br>}</pre><h3>Değerlendirilme ve Çağrılma Sıraları</h3><p>Sınıf dekoratörü new anahtar kelimesi kullanıldığında diğerleri ise bulunduğu method tetiklendiği anda ilk önce değerlendirilir ardından ise çağrılır. Değerlendirme işlemi Decorator Factory kısmında bahsedeceğimiz fonksiyonların gövdesinden ibarettir. İlk önce alana tanımlı olan Factory gövdeleri çalıştırılır ardından ise Factory’nin geri döndüğü ana dekoratör.</p><h4>Üyeler arasındaki sıralama</h4><p>Dekoratörlerin birbirleri arasındaki çağırılma sırası şu şekildedir:</p><p><strong>1-</strong> Parametre dekoratörleri ardından method, erişimci ve son olarak property dekoratörleri sınıftan üretilen instance için çalıştırılır.</p><p><strong>2- </strong>Parametre dekoratörleri ardından method, erişimci ve son olarak property dekoratörleri sınıfın statik üyeleri için çalıştırılır.</p><p><strong>3- </strong>Kurucu fonksiyonların parametre dekoratörleri çalıştırılır.</p><p><strong>4-</strong> Sınıfın dekoratörü çalıştırılır.</p><p>Yani daha akılda kalıcı olacak şekilde söylersek dekoratörler içeriden dışarıya doğru sıralanır. parameter -&gt; method -&gt; accessor -&gt; property -&gt; constructor -&gt; class</p><h4>Aynı üyedeki birden fazla dekoratörün sıralaması</h4><pre>class Kullanıcı{<br>  @a @b @c<br>  function kaydet(){<br>    console.log(&#39;kaydet fonksiyonu çalıştı&#39;);<br>  }<br>}<br>let k = new Kullanıcı();<br>k.kaydet();</pre><p>Bunların çalıştırma sırası alana en yakın olandan en uzak olana doğrudur. Matematikdeki birleşim özelliği bunun en güzel açıklamasıdır a(b(c(kaydet))) veya (a o b o c)(kaydet) fakat değerlendirme sırası ise en dışarıdan en içeriye doğrudur.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/374/1*EXzRI9c3GCrjf-cP2E8Wzw.png" /></figure><h3>Nasıl Kendi Decorator’ımızı Oluştururuz?</h3><p>Her dekoratör ait olduğu üyeyi ve ona ait diğer özellikleri içine alır böylece o üyeyi manipüle edebiliriz.</p><h4>Class Decorator</h4><p>Tek parametresi vardır o da sınıfın constructor fonksiyonudur. Burada sınıfın içine yeni method veya property ekleyebilir yada olanları ezebiliriz.</p><pre>// toString fonksiyonunu ezen ve JSON stringfy yapan dekoratör<br>function toString&lt;T extends Consturctor&gt;(BaseClass: T) {<br>  return class extends BaseClass {<br>    toString() {<br>      return JSON.stringify(this);<br>    }<br>  };<br>}<br><br>@toString<br>class C {<br>  public foo = &quot;foo&quot;;<br>  public num = 24;<br>}</pre><p>Dekoratörün geri dönderdiği değer sınıfla değiştirilecektir.</p><h4>Method Decorator</h4><p>Üç parametresi vardır bunlar sırasıyla: hedef aldığı fonksiyon, fonksiyonun ismi ve method için Property Descriptor tipindeki bit tanımlayıcı.</p><p>Methodu yeniden atamak, method çağrıldığında log’lama ve benzeri işlemler yapmak için kullanılabilir.</p><p>Descriptor içinde şu key’ler bulunur:</p><ul><li>value</li><li>writable</li><li>enumerable</li><li>configurable</li></ul><pre>function logger(target: any, propertyKey: string, descriptor: PropertyDescriptor) {<br>  const original = descriptor.value;<br><br>  descriptor.value = function (...args) {<br>    console.log(&#39;params: &#39;, ...args);<br>    const result = original.call(this, ...args);<br>    console.log(&#39;result: &#39;, result);<br>    return result;<br>  }<br>}<br><br>class C {<br>  @logger<br>  add(x: number, y:number ) {<br>    return x + y;<br>  }<br>}<br><br>const c = new C();<br>c.add(1, 2);<br>// -&gt; params: 1, 2<br>// -&gt; result: 3</pre><p>Kendisini veya yeni bir PropertyDescriptor geri dönmelidir.</p><h4>Property Decorator</h4><p>İki paraketresi vardır ve bunlar sırasıyla bulunduğu sınıfın kendisi ve hedef aldığı property’nin ismidir.</p><p>Genellikle doğrulama yapmak için kullanılır.</p><pre>function resit(target: any, key: string) {<br>  const setter = function (newVal: number) {<br>    if (newVal &lt; 18) {<br>      throw new Error(&quot;Yaş 18&#39;den büyük olmalıdır.&quot;);<br>    }<br>    this[key] = newVal;<br>  };<br><br>  // Property&#39;i tanımlama<br>  Object.defineProperty(target, key, {<br>    set: setter,<br>    enumerable: true,<br>    configurable: true,<br>  });<br>};<br><br>class C{<br>  @resit<br>  yas: number<br>};</pre><p>Geri dönüş değeri yoktur.</p><h4>Accessor Decorator</h4><p>Method dekoratörleriyle aynı parametreleri alır. TypeScript get ve set erişimcileri için tek bir Property Descriptor üretir bu yüzden işlem yapılırken bu göz önünde bulundurulmalıdır. Bu nedenle descriptor yapısı method dekoratörlerinden farklıdır.</p><p>Descriptor içinde şu key’ler bulunur:</p><ul><li>get</li><li>set</li><li>configurable</li><li>enumerable</li></ul><p>Genellikle erişim yapılabilecek durumları düzenlemede, erişim için tetiklendiğinde log’lama yapmak gibi işlemlerde kullanılır.</p><p>Kendisini veya yeni bir PropertyDescriptor geri dönmelidir.</p><h4>Parameter Decorator</h4><p>Üç tane parametresi bulunur ve bunlar sırasıyla: bulunduğu sınıf, bulunduğu method’un ismi ve o method’un kaçıncı parametresi olduğunun index’idir.</p><p>genellikle parametrelerin doğrulanması için kullanılır.</p><pre>function resit(target: any, key: string, index: number) {<br>  const originalMethod = target[key];<br><br>  // Hedef methodun yerine yeni bir method tanımlıyoruz<br>  target[key] = function (...args: any[]) {<br>    const paramValue = args[index];<br>    if (paramValue &lt; 18) {<br>      throw new Error(&quot;Parametre değeri 18&#39;den büyük olmalıdır.&quot;);<br>    }<br>    return originalMethod.apply(this, args);<br>  };<br>}<br><br>class C{<br>  createUser(isim: string, @resit yas: number) {<br>    //...<br>  }<br>}</pre><p>Geriye bir değer döndürmez.</p><h4>Decorator Factory</h4><p>Şu ana kadar nasıl dekoratör oluşturabileceğimizi sistemin bize hangi bilgileri sağladığını ve bunlarla ne yapabileceğimizi gördük peki kendimiz de dışarıdan kendimiz parametre almak istediğimizde ya da dekoratör çağrılmadan önce de bir şeyler yapmak istedimizde ne yapmalıyız sorusuya baş başayız.Bu sorunun cevabı oldukça basit. “Dekoratörü de bir fonksiyonla sarmalıyız.”</p><p>Tek yapmamız gereken almak istediğimiz parametreleri dışarıdan almak ve geriye bir dekoratör döndermek.</p><pre>function büyükMü(sayi){<br>  return function(target, propertyIsmi){<br>    if(target[propertyIsmi] &gt; sayi)<br>      throw new Error(`${propertyIsmi} ${sayi}&#39;dan büyük   olmalıdır.${propertyIsmi}:${target[propertyIsmi]}`);  <br>  }<br>}<br>class Kullanici{<br>  @büyükMü(18)  <br>  yas: number;<br>}</pre><blockquote><strong>Not: </strong>Decorator factory ile oluşturulan dekoratörler mutlaka <em>()</em> ile kullanılmalıdır aksi taktirde sadece factory gövdesi çalışmaktadır.</blockquote><h4>Örnek Senaryo:</h4><p>Şu ana kadar öğrendiklerimizle basit bir routing uygulaması yazabiliriz. Bu uygulama gelen Class ve methodlara verilen dekoratörlere göre gelen istekleri yönlendirecektir. Class’lara path(p: string) isteğin geleceği path’in ana kısmını method’lara ise get , post , delete gibi dekoratörlerle dinleyeceği methodu ve varsa ana path üzerine eklenecek şeyi bilirecektir. Ana uygulama tüm class’ların metalarını toplayıp gelen istekreki path’i ve method’u parçalayarak ilgili method’u çağıracaktır.</p><p>Örnek sınıf:</p><pre>@path(&#39;/users&#39;)<br>class UserController{<br>  @get(&#39;/:id&#39;)<br>  getUser(request, response){}<br>  <br>  @get()<br>  getUsers(req, res){}<br>  <br>  @post()<br>  createUser(req, res){}<br>}</pre><h3><strong>Kaynakça:</strong></h3><ul><li><a href="https://www.typescriptlang.org/docs/handbook/decorators.html#handbook-content">Documentation - Decorators</a></li><li><a href="https://saul-mirone.github.io/a-complete-guide-to-typescript-decorator/">A Complete Guide to TypeScript Decorators</a></li><li><a href="https://www.digitalocean.com/community/tutorials/how-to-use-decorators-in-typescript">How To Use Decorators in TypeScript | DigitalOcean</a></li><li><a href="https://ozanturhan.medium.com/typescript-decorator-nedir-ab95c13f891">Typescript Decorator Nedir?</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5431d4a17a3b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[X11 Forwarding ile Uzak Bilgisayara Arayüz Oluşturmak]]></title>
            <link>https://medium.com/@saracalihan/x11-forwarding-ile-uzak-bilgisayara-aray%C3%BCz-olu%C5%9Fturmak-8602e196650d?source=rss-9e0746732eba------2</link>
            <guid isPermaLink="false">https://medium.com/p/8602e196650d</guid>
            <category><![CDATA[ssh]]></category>
            <category><![CDATA[xlib]]></category>
            <category><![CDATA[remote-connection]]></category>
            <category><![CDATA[servers]]></category>
            <category><![CDATA[devops]]></category>
            <dc:creator><![CDATA[Alihan SARAÇ]]></dc:creator>
            <pubDate>Fri, 05 Apr 2024 08:08:49 GMT</pubDate>
            <atom:updated>2024-04-05T08:09:28.529Z</atom:updated>
            <content:encoded><![CDATA[<p>Bu yazımızda Xlib ile uzak bilgisayara arayüz oluşturmaya değineceğiz.</p><p>Forwarding’i anlayabilmek için gelin ilk önce üstünkörü X11&#39;in nasıl çalıştığına bakalım.</p><h3>Xlib Nedir?</h3><p>C programlama dili ile geliştirilmiş ve Linux dünyasının duayen grafik kütüphanesi haline gelmiş olan Xlib, sunucu ve client mantığı ile çalışır.</p><p>Client(kullanıcı, masaüstü uygulaması) çizim fonksiyonlarını kullanarak X protokolü ile sunucuya istek gönderir. Sunucu gelen isteği yorumlar ve yapılması gereken çizimi hesaplar ve çizdirir.</p><p>Sunucu kendi bilgisayarınızda olabileceği gibi başka bir bilgisayarda da olabilir. Xlib ile uygulama yazarken kodunuzda bunu belirtebilirsiniz veya sisteminize doğrudan varsayılan bir adrese bağlanmasını söyleyebilirsiniz.</p><h3>Uzak Sunucuya Bağlanmak</h3><p>Uzak sunucuya bağlanma ve X11 ile konuşma işini bizim için ssh programları yapar.</p><p>Linux bir bilgisayardan Linux bir sunucuya bağlanmak için doğrudan <strong>ssh </strong>komutunu kullanabiliriz, Windows’tan bağlanmak içinse PuTTY gibi bir ssh client işimizi görecektir.</p><h4>Sunucuyu hazırlamak:</h4><p>X11 yönlendirmesini kullanabilmek için sunucunuza forwarding ayarı yapılmalıdır.</p><p>Sunucunuzda /etc/ssh/sshd_configadresinde bulunan ssh config dosyasına X11Forwarding yes eklemeniz veya # ile başlıyorsa bunu silip yorum satırından çıkarmanız gerekmektedir. Ardından ssh server’ınızı “systemctl” veya “systemd” gibi programlarla yeniden başlattığınızda kullanıma hazırız.</p><blockquote>Güvenlik için lütfen cookie ve XAUTHORITY ayarlarına bakın</blockquote><h4>Sunucuya bağlanmak</h4><p>Linux üzerinde ssh komutunuza -X eklediğinizde X11 yönlendirmesini devreye alacaktır.</p><p>Örnek olarak:</p><pre>ssh -X kullanici@adres.com</pre><p>Windows bilgisayarda ise PuTTY veya kullandığınız ssh client’ının ayarlar bölümünden “X11 Forwarding” alanını aktifleştirmeniz gerekmektedir.</p><p>Sunucuya ssh bağlantısı kurduktan sonra çalıştıracağınız ve normalde arayüz ayağa kaldıran komutların çıktısı otomatik olarak bilgisayarınıza yansıyacaktır.</p><p>Örnek vermemiz gerekirse code . komutunu çalıştırdığınızda VS Code bulunduğunuz klasörü açacaktır. VS Code, dolphin, gedit, gimp ve birçok uygulamayı bu yöntemle uzaktan açabilirsiniz.</p><p>Tüm iletişim internet üzerinden yapıldığı için donanımınıza ve internet hızınıza göre gerçeğe yakın veya ortalama 1 saniye kadar gecikleyle işlemlerinizi gerçekleştirebilirsiniz.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8602e196650d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kodunuzu Daha Anlaşılır ve Otomatik Dokümanlı Yazmanın Kolay Yolu: JSDoc]]></title>
            <link>https://medium.com/@saracalihan/kodunuzu-daha-anla%C5%9F%C4%B1l%C4%B1r-ve-otomatik-dok%C3%BCmanl%C4%B1-yazman%C4%B1n-kolay-yolu-jsdoc-be0867a331ea?source=rss-9e0746732eba------2</link>
            <guid isPermaLink="false">https://medium.com/p/be0867a331ea</guid>
            <category><![CDATA[jsdoc]]></category>
            <category><![CDATA[auto]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[dokümantasyon]]></category>
            <category><![CDATA[documentation]]></category>
            <dc:creator><![CDATA[Alihan SARAÇ]]></dc:creator>
            <pubDate>Thu, 14 Jul 2022 10:40:47 GMT</pubDate>
            <atom:updated>2022-07-14T10:43:11.259Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1008/1*xp2ZA_rLUe7Usd5dseM13Q.png" /></figure><p>Kodumuzun düzgün bir biçimde çalışıp çalışmaması kadar da geliştirilebilir ve anlaşılır olup olmadığı da onun ne kadar kaliteli bir kod olduğunu belirliyor.</p><p>Kodumuzu daha anlaşılabilir en etkili yollarından birisi de onu nitelikli bir şekilde açıklamaktan geçtiğini unutmayalım. Peki gerçekten kaç kişi hem koduna yorum düşüp hem de ayrıca nasıl çalıştığı hakında bir doküman yazıyor? Bir elin parmakları kadar mı? Gelin bu iki işi aynı anda yapmanın kolay yolu olan otomatik doküman oluşturuculara JavaScript dili için bir göz atalım.</p><h3>Otomatik Doküman Oluşturucu Nedir?</h3><p>Otomatik doküman oluşturucu aslında ayrı bir program olup tek yaptığı iş kodunuzu okuyup yorumlamaktır. Bu program kodunuzu string olarak okur, dil yapısına göre parçalar ve eklediğiniz yorumları da kullanarak bir HTML olarak ya da eklentilerle MarkDown gibi formatlarda doküman oluşturabilir, küçük eklemeler yaparak bunları doğrudan websitesi olarak kullanabilirsin.</p><p>Java için <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html">Javadoc</a>, PHP için <a href="https://www.phpdoc.org/">phpDocumantor</a>, JavaScript için ise <a href="https://jsdoc.app/">JSDoc</a> programlarını örnek gösterebiliriz.</p><h3>Avantajları Nelerdir?</h3><ul><li>Kaynak koduna yorum düştüğünüz için kod yabancı kişilerce <strong>daha kolay anlaşılır.</strong></li><li>Kodun kullanımı ve püf noktaları hakkında <strong>ayrıca doküman yazmanıza gerek kalmaz</strong>. Sadece kaynak kodunuza yorum düşmeniz bunu yapmak için yeterlidir.</li><li>Popüler olarak kullanılan çoğu IDE ve bazı text editörler bu yorumları algılar ve kodunuzu kullanırken bu <strong>bilgileri görselleştirerek</strong> hızlı geliştirme yapmanıza olanak tanır.</li><li>JavaScript gibi tip güvensiz diller için sanki derleme yapılıyormuş gibi <strong>tip kontrolü</strong> yapılmasına olanak sağlar</li></ul><h3>Nasıl kullanılır?</h3><p>JSDoc kendi yorumlarının /** ile başlamasını zorunlu tutar. // , /* gibi normal yorum bloğu başlangıçlarını veya ikiden fazla yıldız olanları görmezden gelir.</p><pre>/** JSDoc için uygun yorum yazımı */</pre><pre>/**<br> * Bu şekilde de kullanabilirsiniz<br> */<br>function foo() {<br>}</pre><p>JSDoc’un parser’ının yorumlayacağı her özel kelimeye tag yani <strong>etiket</strong> denir.Etiketler @ karakteri ile başlar.</p><p>Bilgisayarınıza <a href="http://npmjs.com">npm</a>’i kurduktan sonra npm install -g jsdoc ile global olarak bilgisayarınıza veya npm install jsdoc komutu ile lokal olarak sadece şu an üzerinde bulunduğunuz projeye yükleyebilirsiniz.</p><p>Programı çok temel olarak jsdoc &lt;dosya-ismi&gt; şeklinde kullanıabilirsiniz. Bu size out adında bir klasör açacak ve çıktıları içine yükleyecektir. Kendi konfigrasyonunuzu json tipinde bir dosyaya yazarak bunu -c &lt;json-dosyasının-yolu&gt;ekleyeyerek kullanabilirsiniz.</p><p>Detaylar için bkz.:</p><ul><li><a href="https://jsdoc.app/about-configuring-jsdoc.html">Configuring JSDoc with a configuration file</a></li><li><a href="https://jsdoc.app/about-commandline.html">Command-line arguments to JSDoc</a></li></ul><h3>Hangi Etiketler Var?</h3><p>Aynı HTML’de olduğu gibi burada da <strong>block</strong> ve <strong>inline</strong> olmak üzere iki farklı etiket türü bulunuyor. Block etiketler tüm satırı kaplarken, inline etiketler ise satırın içindeki bir veya daha fazla kelimeyi kaplar. Inline etiketler normal yazıdan ayrılabilmek içi { } arasına yazılır.</p><h4><strong>Sıklıkla kullanılan bazı etiketler şöyledir</strong>:</h4><p><strong>Inline etiketler:</strong></p><ul><li>link: Dokümandaki bir yere yahut harici bir bağlantıyı linkler.</li></ul><p><strong>Block etiketler:</strong></p><ul><li>construct : Sınıfa ait kurucu fonksiyonları tanımlarken kullanılır.</li><li>class : Sınıf tanımlarken kullanılır.</li><li>default : Varsayılan değeri belirtir.</li><li>description : Açıklama eklemenizi sağlar.</li><li>summary : description ‘a benzer olsa da daha detaylı olarak anlatım yapılır.</li><li>example : Örnek kullanım gösterirken kullanılır.</li><li>function : Fonksiyon veya methodları tanımlamak için kullanılır.</li><li>param : Fonksiyonun parametrelerini tanımlar. arg veya argument olarak da kullanılır.</li><li>readonly : O alanda sadece okuma işlemi yapılabileceğini anlatır.</li><li>return : Fonksiyonların dönüş değerini belirtir. returns olarak da kullanılır.</li><li>property : Bir nesnenin property’sini tanımlar. prop olarak da kullanılır.</li><li>see : Buna da bakılsa iyi olur dediğiniz linkleri gösterir.</li><li>author : O elemanı yazan kişiyi belirtir.</li><li>type : Tip kontrolü için kullanılır.</li><li>name : Bir nesneye isim vermemizi sağlar.</li><li>callback : Callback fonksiyonlarını tanımlarken kullanılır.</li><li>copyright : Telif hakkı belirtir.</li><li>ignore : Yazıldığı kısmın görmezden JSDoc tarafında görmezden gelinmesini sağlar.</li><li>module : JavaScript modul’ü oluştururken kullanılır.</li><li>namespace : Bir namespace’i tanımlar.</li><li>override : Bir kalıtım alınan ebeveyn özelliğini ezdiğimizi vurgular.</li><li>since : Bu özelliğin eklendiği tarihi gösterir.</li><li>this : this anahtar kelimesinin neyi işaret ettiğinni belirtir.</li><li>throw : Fırlatılacak hatayı gösterir.</li><li>version : Ekleme yapıldığı versiyonu belirtir</li></ul><p>Kullanabileceğiniz tüm etiketlere buradan ulaşabilirsiniz: <a href="https://jsdoc.app/index.html">https://jsdoc.app/index.html</a></p><h3>Örnek Kullanımı</h3><p>Sunucu adındaki modül içindeki portDinle adında, url ve port olarak iki parametre alan, bu bilgileri kullanarak gelen istekleri dinleyen fonksiyonumuz için örnek kullanım şöyle olabilir:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/837/1*ErfxCk3sjG2095FPIHVAgA.png" /></figure><p>VSCode kullanırken fonksiyonun üstüne geldiğimizde çıkan bilgi kutusu:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/628/1*Sf9xgshN8CE2aSYR3uo2_Q.png" /></figure><p>Oluşan doküman:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/777/1*ME-76e4oUs33oJNyW-Sttg.png" /></figure><h3>Kaynakça:</h3><ul><li><a href="https://jsdoc.app/">Index</a></li><li><a href="https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html">Documentation - JSDoc Reference</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=be0867a331ea" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Ne Bu Asenkron Programlama ?]]></title>
            <link>https://medium.com/@saracalihan/ne-bu-asenkron-programlama-4dab0c1eda50?source=rss-9e0746732eba------2</link>
            <guid isPermaLink="false">https://medium.com/p/4dab0c1eda50</guid>
            <category><![CDATA[async-functions]]></category>
            <category><![CDATA[async]]></category>
            <category><![CDATA[asyncawait]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[asynchronous-programming]]></category>
            <dc:creator><![CDATA[Alihan SARAÇ]]></dc:creator>
            <pubDate>Mon, 11 Jul 2022 11:16:54 GMT</pubDate>
            <atom:updated>2022-07-11T11:16:54.754Z</atom:updated>
            <content:encoded><![CDATA[<h3>Ne Bu Asenkron Programlama ?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HQQa8jZLySvSPzIp.jpg" /></figure><p>Çalıştırdığımız kodun nasıl yazıldığı kadar nasıl çalıştığı da hem geliştiriciler hem de kullanıcılar için büyük bir önem taşır. Yazımı kötü olan bir kodun okunması, çalışması ve üzerinde geliştirilme yapılması oldukça zahmetlidir. Kodumuzu clean code prensipleriyle yazsak bile sistemin çalışma sırasındaki işleyişine hakim değilsek bu bize kötü yazılmış kod kadar maaliyet yaratabilir.</p><p>Dosya işlemleri, veritabanlarıyla konuşmak veya ağ üzerinden harici yapılara bağlanmak saniyeler alabilir ve hatta fark bile edemeyeceğimiz hızlarda yapılan temel aritmetik işlemler uç uca eklendikçe artık can sıkıcı bir seviyeye gelebilir. Bilgisayarımızın kodları nasıl işlettiğine, zaman gibi bir maliyeti nasıl kısaltabileceğimize ve “Biliyor musun kodu bir refactor ettim, 2 saniyede çalışan kod 300 milisaniyede takır takır çalıştı.” gibi lafları nasıl kurabileceğimize gelin birlikte bakalım.</p><h3>Programlama Dillerinin İşlemleri Çalıştırma Mantığı Nasıldır?</h3><p>Propramlama dilleri, derleyiciler veya Node.js gibi çalıştırma ortamları kodumuzda bulunan satırları verdiğimiz parametrelere göre yahut dilin kendi yapısına göre ne zaman bir sonraki satıra geçeceğine farklı farklı karar verebilirler.</p><p>Bu işleyişi temel olarak şu şekilde iki bölüme ayırabiliriz:</p><h4>Synchronous / Blocking</h4><p>Arka arkaya birden fazla fonksiyon çağırdığımızda bu işleyiş stilinde her fonksiyon çalıştırılır ardından fonksiyondan cevap gelene kadar kodun bir sonraki adıma geçmesi engellenir.</p><p>Synchronous(senkron) ve Blocking(bloklamalı) yapılarının mantıkları aynı olsa da kullanıldığı yerler farklıdır.</p><p>Network gibi işlerde synchronous kelimesi kullanılırken dosya okuma örneğini verebileceğimiz IO gibi işlemlerinde ise blocking kelimesi kullanılır.</p><h4>Asynchronous / Non-Blocking / Event Based</h4><p>Bu yapıda ise fonksiyonlarımız çağrılır ve cevap gelmesi beklenmeden bir sonraki adıma geçilir. Genellikle birbiriyle mantıksal ilişkisi olmayan görevleri yaparken birinin başlaması için öbürünün bitmesinin gerekmediği durumlarda kullanılır.</p><p>Event based(olay bazlı) yapıda ise daha önceden belirlenmiş olaylar tetiklenmeden çalıştırma yapılmaz. Burada olayların hangi sırayla tanımlandığı değil hangi sırayla tetiklendiği önemlidir. HTML ve JavaScript’teki event’ler bunun en güzel örneğidir. Bu terim de yeni başlayanlar için soru işaretli olduğu için buna da değinmeyi uygun gördüm.</p><h3>async/await Kullanımı</h3><p>C# 5.0, C++20, Python 3.5, F#, Hack, Julia, Dart, Kotlin 1.1, Rust 1.39, Nim 0.9.4, JavaScript ES2017, Swift 5.5, Zig ve bazı eklentilerle birlikte deneysel olarak Scala asenkron porgramlama için uygun koşulları sağlar. Dilden dile bu anahtar kelimelerin yazımı farklılık gösterebilir.</p><p>Bir fonksiyonu asenkron işletebilmek için async ile bunu bildirmeliyiz. Tip güvenli dillerde fonksiyonumuzun dönüş tipini Task veya Promise olarak belirterek dönüşün uzun sürebileceğini belirtip içine generic olarak asıl dönüş tipini yazmalıyız.</p><pre>async Task&lt;int&gt; getUserId(string username){<br>    int id;<br>    // Mantıksal işlemler<br>    return id;<br>}</pre><p>“Senkron programlama tamam ama asenkron proramlama yaparken cevap gelmeden nasıl işime devam edeceğim ki?” sorusunu kendinize sorduysanız gelin bir de await anahtar kelimesine bakalım.</p><p>await ile asenkron işleyişi kırıp cevap gelene kadar işlemi beklenmesi gerektiğini belirtiyoruz.</p><pre>async Task&lt;int&gt; getUserId(string username){<br>    User user = await findUserFromDatabase(username);<br>    return user.id;<br>}</pre><h3>Örnek Senaryo</h3><p>Büyük bir Excell dosyasınında bulunan malzeme bilgilerini okuyacak, her satır için PDF olarak fatura oluşturacak ardından bunları bir kullanıcıya mail atacak ve excell’deki bilgileri veritabanına kaydedecek bir sistemimiz olduğunu düşünelim.</p><p><strong>Bunu yapacak senkron kod basitçe şöyle olurdu:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/536/1*Ssxu_Mgg0Bsc7Q5bvBQxqQ.png" /><figcaption>senkron kod örneği</figcaption></figure><p>Fonsiyonların sırasıyla 1, 2, 2 ve 1 birim zamanda çalıştığını varsayarsak şöyle bir zaman grafik elde ederiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*9AHosYj9_Q2DIVng1Vbrxw.png" /><figcaption>senkron fonksiyon/zaman çizgisi</figcaption></figure><p>Koddaki excellOku ve pdfOlusturVeGetir dışındaki fonksiyonlar birbirinden bağımsızdır. Bundan dolayı onları ayrık olarak çalıştırmayı deneyebiliriz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/605/1*9MLPsRpzWjb6Ezr5B4KlOQ.png" /><figcaption>asenkron kod örneği</figcaption></figure><p>faturaBilgilendirmeMailiGonder ve veritabaninaKaydet fonksiyonları çalıştırılmaya başlanacak ve hemen bir sonraki adıma geçilecek. Buna göre zaman çizelgesi şöyle olurdu:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*_Z-VgKr0OdBHhLRSzm7EFA.png" /><figcaption>asenkron fonksiyon/zaman çizgisi</figcaption></figure><p>Çizelgeden de anlaşılabildiği üzere son iki işi neredeyse aynı anda başlatarak zamandan tasarruf etmemiz mümkün oldu.</p><h3>Sonuç</h3><p>Düzgün kurgulanmış bir asenkron kodla çalışmak bize gözle görülebilir bir zaman kazancı sağlayacaktır. Unutulmamalıdır ki birden fazla yapıyla(fonksiyon, koşul, döngü) ilişki içinde olan verilerimizi korumak için özellikle de ona atama yapılacağı zaman await veya mutex gibi yapılarla o anda sadece bir işlemin onunla ilgilenmesini sağlamalıyız çünkü cpu’daki iş yükü, ağ yoğunluğu gibi belirleyemeyeceğimiz nedenlerden dolayı işlemlerimiz beklediğimizden farklı sürede çalışabilir ve bu da kodda yazdığımız sırayla atama yapılmasına engel olur.</p><h3>Kaynakça:</h3><ul><li><a href="https://stackoverflow.com/questions/7931537/whats-the-difference-between-asynchronous-non-blocking-event-base-architectu">What&#39;s the difference between: Asynchronous, Non-Blocking, Event-Base architectures?</a></li><li><a href="https://en.wikipedia.org/wiki/Async/await">Async/await - Wikipedia</a></li><li><a href="https://en.wikipedia.org/wiki/Asynchrony_(computer_programming)">Asynchrony (computer programming) - Wikipedia</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4dab0c1eda50" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[JavaScript’in Takipçi Nesnesi ‘Proxy’]]></title>
            <link>https://medium.com/@saracalihan/javascriptin-takip%C3%A7i-nesnesi-proxy-d15e4aec5273?source=rss-9e0746732eba------2</link>
            <guid isPermaLink="false">https://medium.com/p/d15e4aec5273</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[javascript-tips]]></category>
            <category><![CDATA[javascript-development]]></category>
            <category><![CDATA[proxy]]></category>
            <dc:creator><![CDATA[Alihan SARAÇ]]></dc:creator>
            <pubDate>Mon, 04 Jul 2022 22:14:58 GMT</pubDate>
            <atom:updated>2022-07-04T22:28:54.951Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/509/0*8Q70zM4_-Ov-_ior" /></figure><p>Bir nesneye her atama(set) veya okuma(get) yapıldığında belirli işlemleri nasıl yapacağımızı hiç düşündünüz mü? OOP kullanılabilen bir dille daha önce uğraştıysanız bu soruya haklı olarak “Tabii ki getter ve setter kullanarak.” cevabını vermiş olabilirsinizdir, JavaScript de bu özelliğe sahiptir ancak asıl nesnemize getter/setter eklemek istemediğimizde veya daha fazla işlemi takip etmek istediğimizde ne kullanacağız peki? İşte burada da <strong>Proxy </strong>nesneleri yardımımıza koşuyor.</p><h3>Proxy Nedir?</h3><p>ECMAScript 6 ile hayatımıza giren Proxy nesnesi, bir objeyi baz alarak get, set, yeni property tanımlama gibi temel obje operasyonlarını takip edebileceğimiz yeni bir obje oluşturur. Bu sayede obje üzerindeki işlemlere göre aksiyona geçebilir, veri doğrulayabilir, serileştirebilir, log’layabilir yahut benzeri işlemleri yapabiliriz.</p><p>Proxy üzerinden hedef nesnenin özellikleri değiştirildikçe hem proxy’deki veriler hem de hedef nesnenin içindekilerin değişeceği kullanılırken göz önünde bulundurulmalıdır.</p><h4>Nasıl tanımlanır?</h4><p>Proxy constructure’ının iki ana parametresi vardır. Bunlardan birincisi kopyasını çıkaracağımız hedef nesne ikincisi ise işlemler tetiklendiğinde çalışacak mantıksal yapımızın olduğu bir handler’dır. Her handler’ın kendine ait parametreleri vardır.</p><pre>// target yerine orijinal nesnemizi,<br>// handler yerine takip fonksiyonlarımızın bulunduğu nesneyi yazarız.<br>// new Proxy(target, handler);</pre><pre>let user = {<br>  name: &#39;Alihan&#39;,<br>  surname: &#39;SARAC&#39;,<br>  age: 21,<br>};</pre><pre>const handler = {<br>  //  ilgili method&#39;lar<br>};</pre><pre>let userProxy = new Proxy(user, handler);</pre><h4>Hangi obje işlemlerini takip edebiliriz?</h4><p>Objelerin temel işlemlerinin birçoğunu takip edebiliriz. Bunların bir kısmı proxy üzerinden tetiklenebilirken bir kısmını da Object sınıfının method’ları ile tetikleyebiliriz.</p><ul><li>get : proxy’den okuma yapıldığında tetiklenir</li><li>set :proxy’e atama yapılırken tetiklenir</li><li>has :<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in">in</a> operatörü kullanıldığında tetiklenir.</li><li>apply : fonksiyondan üretilen proxy’lerde fonksiyon çağrıldığında tetiklenir.</li><li>ownKeys : <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames">Object.getOwnPropertyNames</a> ve <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertySymbols">Object.getOwnPropertySymbols</a> ile proxy kullanıldığında tetiklenir</li><li>construct : new operatörü kullanıldığında tetiklenir</li><li>isExtensible : <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible">Object.isExtensible</a> ile proxy kullanıldığında tetiklenir.</li><li>deleteProperty : <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete">delete</a> operatörü proxy üzerinde kullanılınca tetiklenir.</li><li>defineProperty : <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty">Object.defineProperty</a> ile proxy kullanıldığında tetiklenir.</li><li>setPrototypeOf : <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf">Object.setPrototypeOf</a> ile proxy kullanıldığında tetiklenir.</li><li>getOwnPropertyDescriptor : <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor">Object.getOwnPropertyDescriptor</a> ile proxy çağrıldığında tetiklenir.</li><li>preventExtensions : <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions">Object.preventExtensions</a> ile proxy kullanıldığında tetiklenir.</li></ul><h4>Nasıl kullanılır?</h4><p>Proxy handler method’larının içine tanımlandığı nesnenin güncel halini parametre olarak gönderir. Key(property)’lere özel handler tanımlanamadığı için eğer key’lerle ilgili bir işlem yapılıyorsa key’in ismini de parametre geçer ve ardından ilgili işleme özel parametreleri de gönderir.</p><p>En temel 3 şey olan atama, getirme ve silme işlemlerine gelin birlikte bakalım.</p><p><strong>Get:</strong></p><pre>// target: hedef nesnemizin kendisi<br>// property: okuma işlemi yapılan key<br>// reciever: proxy&#39;nin kendisi yada ondan kalıtım alan bir nesne.<br>//<br>// temel işlemlerde &quot;reciever&quot; kullanmamıza gerek yoktur<br>// sadece ilk iki parametre alınabilir</pre><pre>get( target, property, reciever){<br>  // mantıksal işlemler<br>  return &quot;geri dönülecek değer&quot;;<br>}</pre><p>Get fonksiyonunun içinden target[property] diyerek şu an okuma yapılan değeri alabilir, ilgili işlemleri yaptıktan sonra istediğimiz değeri return diyerek kullanıcıya dönebiliriz.</p><p><strong>Set:</strong></p><pre>// target: hedef nesnemizin kendisi<br>// property: okuma işlemi yapılan key<br>// value: property&#39;e atanmak istenen değerdir<br>// reciever: proxy&#39;nin kendisi yada ondan kalıtım alan bir nesne.<br>//<br>// temel işlemlerde &quot;reciever&quot; kullanmamıza gerek yoktur<br>// sadece ilk iki parametre alınabilir</pre><pre>get( target, property, value, reciever){<br>  // mantıksal işlemler<br>  return true;<br>}</pre><p>Set fonksiyonu mutlaka geriye atama yapıldığına dair bool bir değer dönmelidir. Fonksiyonunun içinden target[property] diyerek atama yapmalısınız.</p><p><strong>Delete:</strong></p><pre>// target: hedef nesnemizin kendisi<br>// property: okuma işlemi yapılan key</pre><pre>deleteProperty( target, property){<br>  // mantıksal işlemler<br>  delete target[property];<br>  return true;<br>}</pre><p>deleteProperty , delete operatörü kullanıldığında tetiklenir ve silinme yapıldığının anlaşılması için bool bir değer döndürmelidir.</p><h4>Geri alınabilir Proxy’ler</h4><p>Eğer Proxy oluştururken Proxy.revocable fonksiyonunu kullanırsak proxy özelliği kapatılabilir bir proxy oluşturmuş oluruz. Oluşturulma şekli ve kullanımı normal proxy ile temel olarak aynıdır, tek fark mu fonksiyonun geriye proxy değil onu verecek ve iptal edecek olan nesneyi vermesidir.</p><pre>let revocable =  Proxy.revocable(target, handler);<br>let userProxy = revocable.proxy;</pre><p>revocable oluşturulduktan sonra revocable.revoke method’u ile proxy nesnesinin proxy’si kapatılır.</p><p><strong>Unutulmamalıdır ki proxy kapatıldıktan sonra yukarıdaki “Hangi obje işlemlerini takip edebiliriz?” alanında bahsedilen tüm operasyonlar </strong><strong>TypeError fırlatacaktır.</strong></p><h3>Örnek Kullanım Senaryoları:</h3><h4>Value Validation:</h4><p>Proxy’lerin en popüler kullanım alanlarından biri de veri doğrulamasıdır. Atama işlemlerinde minimum-maksimum değer, email ve yazım tipi doğrulaması gibi birçok işlemde kullanılabilir.</p><p>Senaryomuzda bir kullanıcı olduğunu varsayalım. Yaş değerinin 0&#39;dan büyük olması gerektiğini, silme işleminde sadece kullanıcının silme tarihi geçtiyse silinebileceğini ve sadece test kullanıcılarının şifresinin okunabileceğini varsayalım.</p><p>Orijinal nesnemizi tanımlayalım.</p><pre>let user = {<br>  name: &#39;alihan&#39;,<br>  age: 21,<br>  password: &#39;123456as.&#39;,<br>  isTestUser: true,<br>  expireAt: new Date(100000000000),<br>}</pre><p>Proxy’nin handler’ını tanımlayalım.</p><pre>const userProxyHandler = {<br>  get(target, key){<br>    let value = target[key];<br>    if(key === &#39;password&#39; &amp;&amp; !isTestUser){<br>      value = &#39;***&#39;;<br>// gelen okuma password için yapılıyorsa ve kullancı test kullanıcısı değilse şifre &#39;***&#39; şeklinde gösterilir.<br>    }<br>    return value;<br>  }</pre><pre>  set(target, key, value){<br>    if(key === &#39;age&#39; &amp;&amp; value &lt; 0){<br>      throw new Error(&#39;yaş değeri 0&#39;a eşit veya büyük olmalıdır&#39;);<br>    }<br>    target[key] = value;<br>    return true;<br>  }</pre><pre>  deleteProperty(target, key){<br>    if(Date.now() &gt; target[expireAt]){<br>      throw new Error(&#39;Kullanıcı bu tarihte silinemez&#39;);<br>    }<br>    delete target[key];<br>  }<br>}</pre><h4>Değişen key’leri ve eski değerlerini nesne içinde tutma:</h4><p>Veritabanlarıyla uğraşıyorsanız, hele de benim gibi bir <a href="https://github.com/anchovycation/metronom">ORM</a> yazmayı deniyorsanız her bir işlemin maliyeti sizin için oldukça önemlidir. İçinde sadece bir alanı değişmiş büyük bir nesneyi sisteme tekrardan kaydetmek gibi bir masraf kesinlikle istemeyeceğimiz bir şeydir bu durumu çözmek için hangi alanlarda değişiklik yapıldığını tutabilir ve sadece o alanı kaydedebiliriz. Proxy‘ler tam da bu iş için yaratılmış. Hadi nasıl yapacağımıza bakalım.</p><p>İlk önce handler’a bir set olayı yazmalıyız. Burada objemizin içinde _degisenDegerler adında, obje tipinde bir key tutacağız ve değişiklikleri buradan takip edebileceğiz. Her set işlemi çalıştığında ilgili key ilk önce target içindeki _degisenDegerler ‘e eklenmeli ve şu anki verisi buraya yazılmalı ardından ise target ‘ın içindeki key alanı gelen value ‘yu tutacak şekilde güncellenmeli böylece eski veri _degisenDegerler içine yazılmış ve yerine yenisi atanmış olur. Veritabanına kayıt yapıldıktan sonra da _degisenDegerler içindeki tüm key’ler kaldırılabilir.</p><pre>let model = {<br>  isim: &#39;Alihan&#39;,<br>  _degisenDegerler: {},<br>};</pre><pre>let modelProxy = new Proxy(model, {<br>  set(target, key, deger){<br>    target._degisenDegerler[key] = target[key];<br>    target[key] = deger;<br>    return true;<br>  }<br>});</pre><pre>modelProxy.isim = &#39;ayşe&#39;;<br>modelProxy.yas=21;</pre><pre>console.log({ modelProxy });</pre><pre>//{<br>//  &quot;modelProxy&quot;: {<br>//    &quot;isim&quot;: &quot;ayşe&quot;,<br>//    &quot;yas&quot;: 21,<br>//    &quot;_degisenDegerler&quot;: {<br>//      isim: &quot;Alihan&quot;<br>//      yas: undefined<br>//    },<br>//  }<br>//}</pre><h3>Kaynakça:</h3><p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy">Proxy - JavaScript | MDN</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d15e4aec5273" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Sunucu Tarafında Kullanıcı Doğrulama Yöntemleri ve Sertifika Bazlı Doğrulama]]></title>
            <link>https://medium.com/@saracalihan/sunucu-taraf%C4%B1nda-kullan%C4%B1c%C4%B1-do%C4%9Frulama-y%C3%B6ntemleri-ve-sertifika-bazl%C4%B1-do%C4%9Frulama-7bd2d0f6b49?source=rss-9e0746732eba------2</link>
            <guid isPermaLink="false">https://medium.com/p/7bd2d0f6b49</guid>
            <category><![CDATA[hash]]></category>
            <category><![CDATA[authentication]]></category>
            <category><![CDATA[ssl-certificate]]></category>
            <category><![CDATA[token]]></category>
            <category><![CDATA[salt]]></category>
            <dc:creator><![CDATA[Alihan SARAÇ]]></dc:creator>
            <pubDate>Fri, 01 Jul 2022 10:57:22 GMT</pubDate>
            <atom:updated>2022-07-01T10:57:22.103Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*KFpf4htuPraok6d-.jpg" /></figure><p>Sunucularımız genellikle herkesin istek atmasına müsait olsa da her kullanıcının istediği bilgiye ulaşması sistemimizi ve diğer kullanıcıları tehlikeye sokabilir bu yüzden isteği atan kullanıcıyı doğrulamamız( <strong>authentication </strong>) ve yetkilendirmemiz( <strong>authorization</strong> ) gerekmektedir. Temel olarak şu kimlik doğrulama yöntemleri kullanılabilir:</p><h4><strong>1 - Password Doğrulaması:</strong></h4><p>Kullanıcı kayıt olurken kullanıcı ismi, müşteri numarası, email adresi gibi benzersiz bir alan sahip olması istenir bu sayede kullanıcı sistemde doğrudan işaret edilebilir ve kullanıcıdan sadece kendisinin bileceği bir şifre tanımlaması istenir böylece kullanıcı adı bilinse bile şifresini sadece kendisi bileceği için sistem görece güvenli olur.</p><p>Veritabanında biraz önce bahsettiğimiz ID alanı herhangi bir gizleme yapılmadan tutulmasında son kullanıcı için bir sakınca yoktur çünkü bu değer şifreye sahip olmayan biri için önemsizdir fakat şifre açık bir şekilde(<strong><em>plain text</em></strong>) tutulduğunda veritabanına yapılacak saldırıda tüm kullanıcıların verisine artık tek hamlede erişilebilmesine yol açar. Bunun önüne geçmek için aşağıdaki gibi birkaç farklı şekilde koruma sağlayabiliriz.</p><p><strong>Karıştırma:</strong></p><p>Karıştırma yapılırken kelime katarındaki karakterler belli bir örüntüye göre yer değiştirilir yahut ötelenirler, çözümleme yapılırken de aynı algoritma tam tersi işletilerek katarın ilk haline ulaşılır.</p><p><strong>Hash’leme:</strong></p><p>Hash’leme, bir algoritma(<strong><em>hash function</em></strong>) ile bir karakter katarını(<strong><em>key</em></strong>) bir daha geri dönüştürülemeyecek şekilde yeni bir karakter katarına dönüştürme işlemidir. Şahsi algoritmanızı tasarlayarak yahut <strong><em>SHA</em></strong><em>, </em><strong><em>CRC</em></strong><em>, </em><strong><em>Fletcher</em></strong><em>, </em><strong><em>MD-2</em></strong> gibi hazır algoritmalar kullanarak bu işlemi yapabiliriz. Zaruret olan bir durum olmadığı müddetçe farklı zümreler tarafından çok farklı koşullarda test edildiğinden dolayı bahsedilen hazır algoritmaların kullanılması tavsiye edilir.</p><p>Hash fonksiyonuna verilen ve içeriği aynı olan girdilerin çıktıları da aynıdır bu sayede sunucuya gönderilen şifre hash’lenerek veritabanında tutulan kullanıcı hash’i ile karşılaştırılabilir.</p><p><strong>Hash-Salt:</strong></p><p>Salt’lama bir karakter katarının bir yerine başka bir kelimeyi ekleme işlemine denir. En basit örneği kelimenin sonuna başka bir kelimeyi eklemektir.</p><p>Şifrelerde Hash’leme işlemi yapılsa bile elimizdeki tüm kombinasyonlar denenerek(<strong><em>brute force</em></strong>) hash’in gerçek karşılığı bir müddet sonra bulunabilir. Bu süreyi arttırmak için şifrelere salt’lama yapılır ve ardından hash’lenir, salt key’i sunucu ortamında tutulduğu için ayrık sistemlerde veritabanı ele geçirilse bile salt değeri bilinmez.</p><p>Şifre salt’landıktan sonra hash’lendiği için aynı hash’e sahip kayıtlardan sadece bir tanesinin bulunması hepsini ifşalayacaktır bundan dolayı salt’lar birbirinden farklı olacak şekilde oluşturulmalıdır. Hash’in ve Salt’ın aynı kayıt içinde tutulması başta güvenli değil gibi görünse de aslında rastgele olmayan salt kullanıldığında brute force ile salt bulunduktan sonra tüm şifrelerin çözülmesi oldukça hızlanacaktır ama salt’lar farklıysa her kayıt için tek tek salt-hash denemesinin yapılması oldukça maliyetli olacaktır.</p><h4><strong>2 - Token Doğrulaması:</strong></h4><p>Token’larla yapılan doğrulamayı basitçe iki arkadaş arasında bulunan gizli bir şifre olarak düşünebiliriz. Bu şifre uzaktan bakıldığında bir anlam ifade etmeyen, benzersiz olan bir karakter katarıdır. Sunucu bu token üretirken benzersiz olduğunu garanti eder ya da aynısından iki tane üretme olasılığı o kadar düşüktür ki bunu ihmal edebilir. Kullanıcı sunucuya istek üzerinden bu token’ı yollayarak kendini tanıtır. HTTP/HTTPS isteklerinde cookie, header, body yahut url içinde olabilir.</p><p>Token doğrulamasına çok benzer olarak <strong>ticket</strong> doğrulaması da vardır. Bunun için verebileceğimiz en popüler örnek <strong>Kerberos protokolüdür</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/767/0*tTGrcClefbJOp8CX" /><figcaption>Kerberos Protokolünün Adım Adım İşleyişi</figcaption></figure><p>Kerberos network üzerinde kullanıcı doğrulaması yapılmasını sağlayan bir protokoldür. Kullanıcı gateway’le konuşur gibi ilk önce bir authentication sunucusuyla konuşur ve sunucudan bir ticket alır ardından bu ticket’ı konuşmak istediği sunucuya iletir ve aralarında veri akışı başlar.</p><h4>3 - OAuth</h4><p>Bazı durumlarda siz ne kadar güvenli bir sistem oluştursanız bile kullanıcı kişisel bilgilerini sisteminize girmek istemeyebilir. Böyle durumlarda kullanıcının güvenebileceği Google, Facebook, Apple gibi sistemlerden giriş yapmasını sağlayıp istediğimiz bilgilere onlar üzerinden ulaşabiliriz.</p><p>Sistemi basitçe şöyle anlatabiliriz:</p><p>Kullanıcı güvendiği sistemde kendini tanıtır ve o sistem bizim daha önce belirlediğimiz verilere ulaşabilmemizi sağlayacak bir token’ı bize iletir ve bu token ile kullanıcıyı doğrulayabilir ve verilerine ulaşabiliriz.</p><h4><strong>4 - Sertifika Bazlı doğrulama:</strong></h4><p>Sertifika bazlı doğrulamada kullanıcı sunucuya kullanıcı bilgisi ve şifre yahut token göndermek yerine tarafsız otoritelerce onaylanmış sertifika dosyasını göndererek bu sertifika <strong>trusted store</strong> denilen sertifika doğrulayıcısı tarafından doğrulanır ve kullanıcı kaynaklara erişebilir hale gelir.</p><p>Doğrulama yapmak için en çok kullanılan biri de HTTPS protokolünün zorunlu kıldığı SSL/TLS sertifikasıdır.</p><p><strong>SSL/TLS’in Çalışma Şekli:</strong></p><ol><li>Kullanıcı “hello” mesajı yollayarak sunucuya güvenli session oluşturmak istediğini söyler</li><li>Server, server sertifikasını, CA bilgisini, ve public key’ini kullanıcıya gönderir</li><li>Kullanıcı sunucu sertifikasını trusted store içinde doğrulatır ve onay gelirse devam eder</li><li>Kullanıcı sunucuya sunucunun public key’ini kullanarak tek seferlik session key gönderir</li><li>Sunucu gelen key’i kendi private key’i ile şifreler ve kullanıcı ile sunucu arasında şifrelenmiş iletişim başlar</li></ol><p>Bu SSL’in işleyişidir ve sadece kullanıcı sunucunun güvenli olduğunu doğrular, kullanıcıyı da doğrulamak için mutual SSL denilen, 3. adımdan sonra 2. ve 3.adımlar sunucu tarafında kullanıcı sertifikası için de yapan, başarılı olursa 4.adımdan devam eden yöntem kullanılmalıdır.</p><p><strong>SSL’le Sunucu Tarafında Kullanıcı Doğrulaması</strong></p><p>Sunucunun isteği kimin tarafından atıldığını bilebilmesi için kullanıcının da bir sertifikası olması gerekmektedir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/793/0*ADbgUEXTrNQq7zLf" /><figcaption>SSL Sertifika Yapısı</figcaption></figure><p><strong>Sertifikanın önemli bazı alanları</strong>:</p><p><strong>version</strong>: Protokolün versiyon numarasıdır.</p><p><strong>certificate serial number</strong>: sertifikaya ait seri numarası.</p><p><strong>Period of validity: </strong>sertifikanın geçerlilik süresi.</p><p><strong>subject name: </strong>sertifika sahibinin bilgileri. İçinde sahibinin ülkesi, bölgesi, şehri, organizasyon ismi ve genel adı tutulabilir.</p><p><strong>Signature: </strong>sertifikanın imzası.</p><p>SSL’le gelecek kullanıcılar, sertifikasında bulunan subject name , Signature veya Thumbprint gibi benzersiz olan alanlarına göre ayırt edilebilir, eğer kullanıcıya ait bir SSL sertifikası yoksa mutual SSL yönteminde sunucunun kendisi tarafından imzalanan(self-signed) bir sertifika oluşturulup kendisine gönderilebilir. <strong>Unutulmamalıdır ki self-signed yöntemi sadece localhost içinde çalışmaktadır.</strong></p><p><strong>Node.js için sertifika doğrulama örneği</strong>: <a href="https://github.com/julie-ng/nodejs-certificate-auth">https://github.com/julie-ng/nodejs-certificate-auth</a></p><p><strong>C# için sertifika doğrulama örneği</strong>: <a href="https://github.com/niteshsinghal85/blogs/tree/main/CertificateAuthExample">https://github.com/niteshsinghal85/blogs/tree/main/CertificateAuthExample</a></p><h4><strong>Tavsiyelerim</strong></h4><p>Kullanıcıya ait bir ip adresinden birden fazla kullanıcı bilgisiyle doğrulamada kullanılabilecek hem kullanıcı hem de sunucu için en maliyetsiz olan yöntem, kullanıcıyı ilk önce hash-salt yöntemi ile doğruladıktan sonra ona kullanabileceği token vererek kullanıcıyı token ile doğrulamaktır çünkü kullanıcı sadece tek sefere mahsus giriş yapar ve ardından sistem tarafından otomatik olarak giriş yaptırtılabilir ama unutulmamalıdır ki bu girişler otomatik olarak yapılabileceği için kullanıcı bilgisi olmadan da giriş yapılmasına sebep olmaktadır, sunucu tarafında iste her girişte girilen şifreyle karşılaştırma yapmak için şifre hash’lenme gerekliliğini ortadan kaldıracaktır.</p><p>Eğer bir domain üzerinde sadece bir kullanıcı bulunacaksa sadece sertifika ile doğrulama yapılabilir çünkü sertifika geldiği ve gideceği adresi her zaman taahhüt eder.</p><h3>Kaynakça:</h3><iframe src="https://drive.google.com/viewerng/viewer?url=https%3A//dergipark.org.tr/tr/download/article-file/319383&amp;embedded=true" width="600" height="780" frameborder="0" scrolling="no"><a href="https://medium.com/media/3b7449a39ecbea0346c7c4dab3ffe8b0/href">https://medium.com/media/3b7449a39ecbea0346c7c4dab3ffe8b0/href</a></iframe><ul><li><a href="https://www.ssl2buy.com/wiki/ssl-vs-tls">SSL vs. TLS - What are differences?</a></li><li><a href="https://en.wikipedia.org/wiki/Certificate_authority">Certificate authority - Wikipedia</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7bd2d0f6b49" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[C# Attribute’lara Derinlemesine Bakış]]></title>
            <link>https://medium.com/@saracalihan/c-attributelara-derinlemesine-bak%C4%B1%C5%9F-e34384aec49a?source=rss-9e0746732eba------2</link>
            <guid isPermaLink="false">https://medium.com/p/e34384aec49a</guid>
            <category><![CDATA[dotnet-core]]></category>
            <category><![CDATA[c-sharp-language]]></category>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[attributes]]></category>
            <category><![CDATA[aspnetcore]]></category>
            <dc:creator><![CDATA[Alihan SARAÇ]]></dc:creator>
            <pubDate>Tue, 28 Jun 2022 11:39:17 GMT</pubDate>
            <atom:updated>2022-06-28T13:16:11.378Z</atom:updated>
            <content:encoded><![CDATA[<h3>Başlangıç</h3><p>Eğer C# ile herhangi bir Back-End içeren uygulama yazdıysanız illa ki köşeli parantezlerin içine yazılan, sanki kod yazarken koda başlık düşmüşüz gibi görülen kelimelerle karşılaşmışsınızdır. Peki bunların ne olduğunu, kullanımını ve arka planda nasıl çalıştıklarını hiç merak ettiniz mi? Hadi gelin bunları derinlemesine inceleyelim ve örnekleriyle anlayalım.</p><h3>Attribute Nedir?</h3><p>Öznitelik veya filtre olarak Türkçeye çevirebileceğimiz Attribute’lar, ilk bakışta geliştiricilere kod hakkında bilgi verici zımbırtılar olarak görünse de aslında kodun çalışma zamanında(<strong><em>run time</em></strong>) assembly, type, class, method, property ve benzeri şeylerle etkileşime girmek ve ilişkilendirmek için kullanılan bir özelliktir.</p><p>Attribute’lar, assembly’lere programımız hakkında bilgileri içeren Metadata’ları iletmemize olanak sağlar. Derleyiciler, kullandığımız paketler veya kodumuzun ta kendisi bu bilgileri okuyarak klasik işleyişi yerine farklı yöntemlerle işini gerçekleştirebilir böylece daha kolay ve esnek şekilde kod yazabiliriz.</p><p>Şu ana kadar temel olarak Attribute’ları konuştuk. Şimdi de hadi biraz teknik açıdan bakalım.</p><h4>Nasıl kullanılır:</h4><p>Attribute’ların en popüler kullanım yerlerini class’lar, method’lar ve property’lerdir. Bu alanların öncesine yahut bir üst satırına köşeli parantezler içine attribute ismi yazılır.</p><pre>[AttributeA] public class User{<br>    [AttributeB]<br>    public string name { get; set; }<br>    public bool setPassword([In][Out] ref double x) { }<br>}</pre><p>Bu kullanım Attribute’ü ilgili yerde aktif hale getirir.</p><p>Eğer Attribute’unuza derleyicinin just-in-time anında bilmesini istediğiniz bir metadata aktarmak istiyorsanız bunu parametrelerini kullanarak yapabilirsiniz. Normal bir constructor kullanır gibi sırayla parametre girebilir veya parametrenin ismini kullanarak atama yapabilirsiniz.</p><pre>[Author(&quot;P. Ackerman&quot;, version = 1.1)]<br>class Users{<br>    // P. Ackerman için bazı mantıksal işlemler.<br>}</pre><p>Aynı alan için yukarıdan aşağıya yahut soldan sağa birden fazla attribute yazabilirsiniz. Kullandığınız mantıksal yapıya göre bunların sırası önem gösterecektir.</p><p>Attribute’ları nasıl kullanadığımızı anladıysak şimdi de sistemin bize hangi attribute’ları verdiğine bakalım ve ardından kendi attribute’larımızı nasıl yazabileceğimizi konuşalım.</p><h4>Build-in attribute’lar:</h4><p><strong>Obsolete</strong>: Kodunuzda artık kullanılmasını tavsiye etmediğiniz yerleri belirtmenize yarar. Derleyici bu alanlar kullanıldığında uyarı verir.</p><pre>public class Users{<br>[ObsoleteAttribute(&quot;Bu fonksiyon guvenlik nedeniyle artik kullanilmamaktadır. Lutfen &#39;guncelSifreFonksiyonu&#39; methodunu kullanin!&quot;)]<br>    public string tehlikeliSifreOluşturmaFonksiyonu() { }<br>    public string guncelSifreFonksiyonu(){}<br>}</pre><p>tehlikeliSifreOluşturmaFonksiyonu çağrıldığında terminalde göreceğimiz çıktı şu şekildedir:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_bOJ--ndgHKg2mTojqV4jA.png" /><figcaption><strong>Derleyicinin verdiği obsolete uyarısı</strong></figcaption></figure><p><strong>Conditional</strong>: Derleyicinin belirlediğimiz koşullar varsa o alanı çalıştırmasına olanak sağlar.</p><pre>public class Users{<br>    [Conditional(&quot;DEBUG&quot;)] <br>    public void tumBilgileriYazdir() { }<br>}</pre><p>tumBilgileriYazdir fonksiyonu sadece “<em>DEBUG</em>” modundayken çalışır. Derleyici ayarlarınıza göre hata veya uyarı fırlatabilir ya da hiçbir şey göstermeyebilir. Sadece sistem durumlarını değil define anahtar kelimesi ile derleyiciye kendi tanımlayacağınız durumları da belirtebilirsiniz.</p><p><em>Bkz</em>.: <a href="https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.conditionalattribute?view=net-6.0#examples"><em>https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.conditionalattribute?view=net-6.0#examples</em></a></p><p><strong>Serializable: </strong>Sınıflarınızın serileştirilebileceğini belirtir.</p><p><strong>NonSerialized: </strong>Sınıflarınızın serileştirilemeyeceğini belirtir.</p><p><strong>DLLImport</strong>: Yolunu vereceğiniz DLL’i kodunuza almanızı sağlar.</p><p>Bunlar En çok kullanıldığını düşündüğüm attribute’lardı fakat sistemde onlarca farklı attribute kurulu olarak gelmektedir.</p><h4>Custom attribute oluşturmak:</h4><p>Sıradan olmayan bir kod yazıyorsanız kendi işleyişinize uygun bir attribute bulmakta zorlandığınızda özel bir attribute’a ihtiyacınız olduğunu hissettiğinizde tek yapmanız gereken System.Attribute sınıfından kalıtım alarak kişisel bir attribute oluşturmak.</p><p>Senaryomuzda otomatik olarak fonksiyon çalıştığında log’lama yapılması gereksin ve içerisine bir mesaj ile birlikte log’lanma seviyesini alsın. Eğer iki bilgi de girilmediyse kullanıcıya uyarı versin. Bu işlemi yapacak kod aşağıdaki gibi olabilir:</p><pre>using System;</pre><pre>[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]</pre><pre>public class LoglayiciAttribute : Attribute {<br>    private string dosyaIsmi = &quot;Log.txt&quot;;<br>    private string mesaj;<br>    public int logSeviyesi;</pre><pre>public LoglayiciAttribute(string mesaj){<br>        this.mesaj = mesaj;<br>        logSeviyesi = 1;<br>        dosyayaYaz();<br>    }</pre><pre>public LoglayiciAttribute(){<br>        // Kullanıcıya parametre vermediğimizde uyarı verecek kod<br>    }</pre><pre>private void dosyayaYaz(){<br>    // dosyaIsmi, mesaj ve logSeviyesi bilgilerini kullanarak dosyaya yazma islemleri<br>    }<br>}</pre><p>AttributeUsage ile attribute’umuzun nerelerde ve nasıl çalışabileceğini belirliyoruz. Bu örneğimizde sadece method’larda çalışmasını istediğimiz AttributeTargets.Method değerini seçtik. Birden fazla yerde kullanılmasını istiyorsanız alanlar arasında | işareti koyarak yazabilirsiniz veya AttributeTargets.All<em> </em>diyebilirsiniz.</p><p>Kullanımı ise şu şekildedir:</p><pre>[LoglayiciAttribute(&quot;Kod kullaniciSil fonksiyonuna girdi&quot;, logSeviyesi = 2)]<br>public bool kullaniciSil(int id){ }</pre><p>Kullandığınız C# ortamının versiyonuna göre değişmekle birlikte attribute sınıfının ismini Attribute ile bitirseniz bile kullanırken sadece Loglayici diyerek de kullanabilirsiniz.</p><h4>Attribute’ları middleware gibi kullanabilir miyiz? Method’lara giden parametrelere erişebilir miyiz?</h4><p>Attribute’lar metadata üretmek için kullanılan yapılardır. Normalde Web API yazarken kullanabileceğiniz attribute’larla bir method’un parametrelerine veya controller’dan gönderilen bilgilere erişebilmek pek mümkün değildir fakat ASP.NET MVC yapısının bize sunduğu ActionFilter yapısı ile dolaylı yoldan bunu başarabiliriz. Action Filter bize aşağıdaki gibi 4 ana interface sunar.</p><ul><li><a href="https://msdn.microsoft.com/en-us/library/system.web.mvc.iauthorizationfilter%28v=vs.118%29.aspx">IAuthorizationFilter</a></li><li><a href="https://msdn.microsoft.com/en-us/library/system.web.mvc.iactionfilter%28v=vs.118%29.aspx">IActionFilter</a></li><li><a href="https://msdn.microsoft.com/en-us/library/system.web.mvc.iresultfilter%28v=vs.118%29.aspx">IResultFilter</a></li><li><a href="https://msdn.microsoft.com/en-us/library/system.web.mvc.iexceptionfilter%28v=vs.118%29.aspx">IExceptionFilter</a></li></ul><p>Bu interface’lerden implemente edilmiş Attribute sınıflarından kalıtım alarak kısıtlı da olsa interface’ler üzerinden gelen bilgilerle bazı işlemlerimizi yapabilir, constructor’ı içinde middleware gibi davranmasını sağlayabilir, authorization(yetkilendirme) ve benzeri şeyleri yapabiliriz.</p><p>Fonksiyon parametrelerine erişme konusuna gelirsek bu pek mümkün değil ancak Web API yazıyorsak Controller’da bulunan HttpContext’e Action Filter üzerinden erişebilir ancak attribute’a parametre olarak klonlanan verinin tipi ref veya out olmadığı için controller’a gönderilen HttpContext değiştirilemez.</p><p><strong>Unutulmamalıdır ki bu yöntem sadece Action Filter’ların kullanılabildiği yerlerde gerçeklenebilir.</strong></p><h4>Bir tipe bağlı attribute’ları bulmak:</h4><p>Buraya kadar bir Attribute’u nasıl kullanacağımızı, nasıl kendimiz oluşturabileceğimizi konuştuk peki kimin hangi attribute’a sahip olduğunu nasıl öğreniriz ve buna karşılık neler yapabiliriz isterseniz de biraz bunları konuşalım.</p><p>Yazının en başında bahsettiğimiz her alanın içine hangi attribute’lara sahip olduğu sistem tarafından içine gömülür. Doğrudan bir tipin sahip olduğu attribute’ları sorgulayarak kod üzerinde örneğin sınıfları gruplayabilir veya bir nesnenin methodlarına mantıksal işlemler yapabiliriz.</p><p>Alanların custom attribute’larını getirmek için MemberInfo.getCustomAttributesData veya MemberInfo.GetCustomAttributes fonksiyonunu kullanmamız yeterlidir. İlk önce System.Reflection türünde olan alanın tipine erişmemiz lazım.</p><p>Tipin içinde bulunan GetCustomAttributes fonksiyonuna istediğiniz attribute tipini parametre veya generic olarak vererek arama yapabiliriz.</p><p>Attribute’a ulaştıktan sonra constructure ile içine verdiğimiz parametreler gibi normal bir sınıftan erişebileceğiniz her bilgiye erişebiliriz.</p><p><strong>Sınıfın custom attribute’larına erişim</strong>:</p><p>Users adında bir sınıfımız olduğunu varsayalım, tipine iki farklı yöntemde erişip ardından attribute’ları sorgulayabiliriz.</p><pre>// 1) typeof operatörüyle<br>System.Reflection.Type sinifTipi = typeof(Users);</pre><pre>// 2) nesnesinin getType methoduyla<br>Users u = new Users();<br>sinifTipi = u.getType();</pre><pre>sinifTipi.GetCustomAttributes( aranacak_Attribute_Tipi );<br>// sinifTipi.GetCustomAttributes&lt; aranacak_Attribute_Tipi &gt;()</pre><p><strong>Method custom attribute’larına erişim</strong>:</p><p>Sınıf tipine eriştikten sonra methodlarına oradan da method’un sahip olduğu attribute’lara erişebiliriz.</p><pre>// Sınıfa ait tüm methodları getirir<br>System.Reflection.MethodInfo[] methodlar = sinifTipi.GetMethods();</pre><pre>// İstediğimiz methodu seçeriz ve &quot;method&quot; adındaki değişkene atarsak<br>method.GetCustomAttributes( //... ) </pre><p><strong>Parametrelerin custom attribute’larına erişim</strong>:</p><p>Bir methoda eriştikten sonra parametrelerine erişebilir ve yukarıda yaptığımız işleri aynı şekilde yapabiliriz.</p><pre>System.Reflection.ParameterInfo[] parametreler = method.GetParameters();</pre><pre>// ardından istediğimiz parametreyi seçeriz ve<br>// GetCustomAttributes ile ilgili işlemleri yaparız</pre><h3>Gerçek Dünya Problemleri ve Kullanımı</h3><p>Attribute’lar hakkında yeterince bilgi sahibi olduk artık gerçek dünyada hem middleware olarak hem de metadata bilgilerini kullanarak nasıl çözümler bulabiliriz onlara bakalım.</p><h4>1 ) Middleware gibi kullanıp yetkilendirme yapmak:</h4><p>Yaptığım bir işte kullanıcı bazı end-pointlere sadece kendine ait SSL sertifikası da gönderildiyse kaynağa ulaşılabilmesini istedi. Burada işi middleware kullanarak ve url filtrelemesi yaparak çözebilirdim fakat bu bana Startup.cs ‘te karışık bir kod olmasına mâl olacaktı bu yüzden acaba attribute haline getirip istediğim yerlerde kullanabilir miyim dedim ve şöyle bir kod ortaya çıktı:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/127d8a0525882683ae8206711e671d1b/href">https://medium.com/media/127d8a0525882683ae8206711e671d1b/href</a></iframe><p>Bilgisayarın local’inde bulunan kullanıcıya ait tüm sertifikaları okur, interface sayesinde gelen HttpContext üzerinden kullanıcıdan yolladığı sertifikayı alır ve sistemdekilerle karşılaştırır eğer karşılığı yoksa HttpContext.Result üzerinden hata fırlatır.</p><h4>2 ) Metadata olarak kullanıp API’ın route haritasını çıkarmak:</h4><p>Daha önce bahsettiğimiz gibi attribute’lar sayesinde kodun belirli kısımlarına anlam yükleyebiliyoruz. Bu yüklediğimiz anlama göre objelerin içine veri eklemek, silmek, onları filtrelemek, farklı durumlarda fonksiyonları dinamik olarak çalıştırmak gibi onlarca faklı iş yapabiliriz biz ise bu örneğimizde ASP.NET yapısından hakim olduğumuz Controller attribute’larını kullanarak arka planda nasıl oluyor da bir route haritası çıkarılıyor buna bakacağız.</p><p>Biz bu örneği konudan sapmamak için sadece bir class için yapacağız fakat kodunuza “controllers” namespace’i altındaki tüm sınıfları da getirip bir döngü ile tüm controller’ları bu işe dahil edebilirisiniz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f299d290104ed6b68700987cf18dbbb3/href">https://medium.com/media/f299d290104ed6b68700987cf18dbbb3/href</a></iframe><p>Buradaki requestMethod, urlve method değişkenine artık istediğimiz şeyleri yapabiliriz. İstersek konsola basabilir istersek de url ‘i dinleyerek requestMethod tipinde istek geldiğinde method ‘u çalıştırabiliriz.</p><h3>Kaynakça:</h3><ul><li><a href="https://www.c-sharpcorner.com/article/walkthrough-c-sharp-attributes/">A Walkthrough of C# Attributes</a></li><li><a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/">Attributes (C#)</a></li><li><a href="https://stackoverflow.com/questions/10435403/how-to-plug-method-parameters-into-custom-attribute">How to plug method parameters into custom attribute</a></li></ul><p><a href="https://stackoverflow.com/a/2677415/14742463">https://stackoverflow.com/questions/2676603/how-do-attribute-classes-work</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e34384aec49a" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>